From bb85869303f71724ee88782a95df6c4eb9bdd559 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sun, 12 Jun 2022 21:19:28 -0700 Subject: [PATCH 01/19] Lots of documentation tweaks --- .../ReducerInterface_GenericDistribution.res | 1 + packages/website/.prettierignore | 1 + packages/website/docs/Api/Date.md | 23 +- packages/website/docs/Api/Dictionary.md | 27 ++ packages/website/docs/Api/DistGeneric.mdx | 306 +++++++++--------- packages/website/docs/Api/DistPointSet.md | 28 ++ packages/website/docs/Api/Duration.mdx | 4 + ...ributions.mdx => DistributionCreation.mdx} | 18 +- packages/website/docs/Guides/Functions.mdx | 8 +- packages/website/docs/Internal/Invariants.md | 8 +- .../Processing-Confidence-Intervals.md | 2 +- packages/website/docusaurus.config.js | 2 +- 12 files changed, 239 insertions(+), 189 deletions(-) rename packages/website/docs/Guides/{Distributions.mdx => DistributionCreation.mdx} (95%) diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index 6ef3f7a6..6d98d724 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -273,6 +273,7 @@ let dispatchToGenericOutput = ( | ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist, ~env) | ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist, ~env) | ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env) + | ("quantile", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env) | ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) => Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env) | ("toSampleSet", [EvDistribution(dist)]) => diff --git a/packages/website/.prettierignore b/packages/website/.prettierignore index d858cd65..fcce6937 100644 --- a/packages/website/.prettierignore +++ b/packages/website/.prettierignore @@ -1,2 +1,3 @@ .docusaurus build +docs/Api/.* \ No newline at end of file diff --git a/packages/website/docs/Api/Date.md b/packages/website/docs/Api/Date.md index 4c50f582..deccdad3 100644 --- a/packages/website/docs/Api/Date.md +++ b/packages/website/docs/Api/Date.md @@ -3,7 +3,10 @@ sidebar_position: 1 title: Date --- +Squiggle date types are a very simple implementation on [Javascript's Date type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date). It's mainly here for early experimentation. There are more relevant functions for the [Duration](/docs/Api/Duration) type. + ### makeFromYear +(Now ``makeDateFromYear``) ``` Date.makeFromYear: (number) => date @@ -19,6 +22,16 @@ makeFromYear(2022.32); toString: (date) => string ``` +### add + +``` +add: (date, duration) => date +``` + +```js +makeFromYear(2022.32) + years(5); +``` + ### subtract ``` @@ -30,13 +43,3 @@ subtract: (date, duration) => date makeFromYear(2040) - makeFromYear(2020); // 20 years makeFromYear(2040) - years(20); // 2020 ``` - -### add - -``` -add: (date, duration) => date -``` - -```js -makeFromYear(2022.32) + years(5); -``` diff --git a/packages/website/docs/Api/Dictionary.md b/packages/website/docs/Api/Dictionary.md index 136342d2..0152f122 100644 --- a/packages/website/docs/Api/Dictionary.md +++ b/packages/website/docs/Api/Dictionary.md @@ -3,6 +3,33 @@ sidebar_position: 2 title: Dictionary --- +Squiggle dictionaries work similar to Python dictionaries. The syntax is similar to objects in Javascript. + +Dictionaries are unordered and duplicates are not allowed. They are meant to be immutable, like most types in Squiggle. + +**Example** +```javascript +valueFromOfficeItems = { + keyboard: 1, + chair: 0.01 to 0.5, + headphones: "ToDo" +} + +valueFromHomeItems = { + monitor: 1, + bed: 0.2 to 0.6, + lights: 0.02 to 0.2, + coffee: 5 to 20 +} + +homeToItemsConversion = 0.1 to 0.4 + +conversionFn(i) = [i[0], i[1] * homeToItemsConversion] +updatedValueFromHomeItems = valueFromHomeItems |> Dict.toList |> map(conversionFn) |> Dict.fromList + +allItems = merge(valueFromOfficeItems, updatedValueFromHomeItems) +``` + ### toList ``` diff --git a/packages/website/docs/Api/DistGeneric.mdx b/packages/website/docs/Api/DistGeneric.mdx index d70476e5..4e91543c 100644 --- a/packages/website/docs/Api/DistGeneric.mdx +++ b/packages/website/docs/Api/DistGeneric.mdx @@ -3,140 +3,141 @@ sidebar_position: 3 title: Distribution --- -import TOCInline from "@theme/TOCInline"; +Distributions are the flagship data type in Squiggle. The distribution type is a generic data type that contains one of three different formats of distributions. +These subtypes are [point set](/docs/Api/DistPointSet), [sample set](/docs/Api/DistSampleSet), and symbolic. The first two of these have a few custom functions that only work on them. You can read more about the differences between these formats [here](/docs/Discussions/Three-Formats-Of-Distributions). + +Several functions below only can work on particular distribution formats. +For example, scoring and pointwise math requires the point set format. When this happens, the types are automatically converted to the correct format. These conversions are lossy. + +import TOCInline from "@theme/TOCInline" ## Distribution Creation -### Normal Distribution +These are functions for creating primative distributions. Many of these could optionally take in distributions as inputs; in these cases, Monte Carlo Sampling will be used to generate the greater distribution. This can be used for simple hierarchical models. + +See a longer tutorial on creating distributions [here](/docs/Guides/DistributionCreation). + +### Normal **Definitions** ```javascript -normal: (frValueDistOrNumber, frValueDistOrNumber) => distribution; -``` - -```javascript -normal: (dict<{p5: frValueDistOrNumber, p95: frValueDistOrNumber}>) => distribution -``` - -```javascript -normal: (dict<{mean: frValueDistOrNumber, stdev: frValueDistOrNumber}>) => distribution +normal: (distribution|number, distribution|number) => distribution +normal: (dict<{p5: distribution|number, p95: distribution|number}>) => distribution +normal: (dict<{mean: distribution|number, stdev: distribution|number}>) => distribution ``` **Examples** ```js -normal(5, 1); -normal({ p5: 4, p95: 10 }); -normal({ mean: 5, stdev: 2 }); +normal(5, 1) +normal({ p5: 4, p95: 10 }) +normal({ mean: 5, stdev: 2 }) +normal(5 to 10, normal(3, 2)) +normal({ mean: uniform(5, 9), stdev: 3 }) ``` -### Lognormal Distribution +### Lognormal **Definitions** ```javascript -lognormal: (frValueDistOrNumber, frValueDistOrNumber) => distribution; -``` - -```javascript -lognormal: (dict<{p5: frValueDistOrNumber, p95: frValueDistOrNumber}>) => distribution -``` - -```javascript -lognormal: (dict<{mean: frValueDistOrNumber, stdev: frValueDistOrNumber}>) => distribution +lognormal: (distribution|number, distribution|number) => distribution +lognormal: (dict<{p5: distribution|number, p95: distribution|number}>) => distribution +lognormal: (dict<{mean: distribution|number, stdev: distribution|number}>) => distribution ``` **Examples** ```javascript -lognormal(0.5, 0.8); -lognormal({ p5: 4, p95: 10 }); -lognormal({ mean: 5, stdev: 2 }); +lognormal(0.5, 0.8) +lognormal({ p5: 4, p95: 10 }) +lognormal({ mean: 5, stdev: 2 }) ``` -### Uniform Distribution +### Uniform **Definitions** ```javascript -uniform: (frValueDistOrNumber, frValueDistOrNumber) => distribution; +uniform: (distribution|number, distribution|number) => distribution ``` **Examples** ```javascript -uniform(10, 12); +uniform(10, 12) ``` -### Beta Distribution +### Beta **Definitions** ```javascript -beta: (frValueDistOrNumber, frValueDistOrNumber) => distribution; +beta: (distribution|number, distribution|number) => distribution ``` **Examples** ```javascript -beta(20, 25); +beta(20, 25) ``` -### Cauchy Distribution +### Cauchy **Definitions** ```javascript -cauchy: (frValueDistOrNumber, frValueDistOrNumber) => distribution; +cauchy: (distribution|number, distribution|number) => distribution ``` **Examples** ```javascript -cauchy(5, 1); +cauchy(5, 1) ``` -### Gamma Distribution +### Gamma **Definitions** ```javascript -gamma: (frValueDistOrNumber, frValueDistOrNumber) => distribution; +gamma: (distribution|number, distribution|number) => distribution ``` **Examples** ```javascript -gamma(5, 1); +gamma(5, 1) ``` -### Logistic Distribution +### Logistic **Definitions** ```javascript -logistic: (frValueDistOrNumber, frValueDistOrNumber) => distribution; +logistic: (distribution|number, distribution|number) => distribution ``` **Examples** ```javascript -gamma(5, 1); +gamma(5, 1) ``` ### To (Distribution) +The `to` function is an easy way to generate simple distributions using predicted _5th_ and _95th_ percentiles. + +If both values are above zero, a `lognormal` distribution is used. If not, a `normal` distribution is used. + **Definitions** ```javascript -to: (frValueDistOrNumber, frValueDistOrNumber) => distribution; -``` - -```javascript -credibleIntervalToDistribution(frValueDistOrNumber, frValueDistOrNumber) => distribution; +to: (distribution|number, distribution|number) => distribution +credibleIntervalToDistribution(distribution|number, distribution|number) => distribution ``` **Examples** @@ -152,13 +153,13 @@ to(5,10) **Definitions** ```javascript -exponential: (frValueDistOrNumber) => distribution; +exponential: (distribution|number) => distribution ``` **Examples** ```javascript -exponential(2); +exponential(2) ``` ### Bernoulli @@ -166,55 +167,13 @@ exponential(2); **Definitions** ```javascript -bernoulli: (frValueDistOrNumber) => distribution; +bernoulli: (distribution|number) => distribution ``` **Examples** ```javascript -bernoulli(0.5); -``` - -### toContinuousPointSet - -Converts a set of points to a continuous distribution - -**Definitions** - -```javascript -toContinuousPointSet: (array>) => distribution -``` - -**Examples** - -```javascript -toContinuousPointSet([ - { x: 0, y: 0.1 }, - { x: 1, y: 0.2 }, - { x: 2, y: 0.15 }, - { x: 3, y: 0.1 }, -]); -``` - -### toDiscretePointSet - -Converts a set of points to a discrete distribution - -**Definitions** - -```javascript -toDiscretePointSet: (array>) => distribution -``` - -**Examples** - -```javascript -toDiscretePointSet([ - { x: 0, y: 0.1 }, - { x: 1, y: 0.2 }, - { x: 2, y: 0.15 }, - { x: 3, y: 0.1 }, -]); +bernoulli(0.5) ``` ## Functions @@ -222,19 +181,21 @@ toDiscretePointSet([ ### mixture ```javascript -mixture: (...distributionLike, weights:list) => distribution +mixture: (...distributionLike, weights?:list) => distribution +mixture: (list, weights?:list) => distribution ``` **Examples** ```javascript -mixture(normal(5, 1), normal(10, 1)); -mx(normal(5, 1), normal(10, 1), [0.3, 0.7]); +mixture(normal(5, 1), normal(10, 1), 8) +mx(normal(5, 1), normal(10, 1), [0.3, 0.7]) +mx([normal(5, 1), normal(10, 1)], [0.3, 0.7]) ``` ### sample -Get one random sample from the distribution +One random sample from the distribution ```javascript sample(distribution) => number @@ -243,12 +204,12 @@ sample(distribution) => number **Examples** ```javascript -sample(normal(5, 2)); +sample(normal(5, 2)) ``` ### sampleN -Get n random samples from the distribution +N random samples from the distribution ```javascript sampleN: (distribution, number) => list @@ -257,75 +218,79 @@ sampleN: (distribution, number) => list **Examples** ```javascript -sample: normal(5, 2), 100; +sampleN(normal(5, 2), 100) ``` ### mean -Get the distribution mean +The distribution mean ```javascript -mean: (distribution) => number; +mean: (distribution) => number ``` **Examples** ```javascript -mean: normal(5, 2); +mean(normal(5, 2)) ``` ### stdev +Standard deviation. Only works now on sample set distributions (so converts other distributions into sample set in order to calculate.) + ```javascript -stdev: (distribution) => number; +stdev: (distribution) => number ``` ### variance +Variance. Similar to stdev, only works now on sample set distributions. + ```javascript -variance: (distribution) => number; +variance: (distribution) => number ``` ### mode ```javascript -mode: (distribution) => number; +mode: (distribution) => number ``` ### cdf ```javascript -cdf: (distribution, number) => number; +cdf: (distribution, number) => number ``` **Examples** ```javascript -cdf: normal(5, 2), 3; +cdf(normal(5, 2), 3) ``` ### pdf ```javascript -pdf: (distribution, number) => number; +pdf: (distribution, number) => number ``` **Examples** ```javascript -pdf(normal(5, 2), 3); +pdf(normal(5, 2), 3) ``` -### inv +### quantile ```javascript -inv: (distribution, number) => number; +quantile: (distribution, number) => number ``` **Examples** ```javascript -inv(normal(5, 2), 0.5); +quantile(normal(5, 2), 0.5) ``` ### toPointSet @@ -333,13 +298,13 @@ inv(normal(5, 2), 0.5); Converts a distribution to the pointSet format ```javascript -toPointSet: (distribution) => pointSetDistribution; +toPointSet: (distribution) => pointSetDistribution ``` **Examples** ```javascript -toPointSet(normal(5, 2)); +toPointSet(normal(5, 2)) ``` ### toSampleSet @@ -347,13 +312,13 @@ toPointSet(normal(5, 2)); Converts a distribution to the sampleSet format, with n samples ```javascript -toSampleSet: (distribution, number) => sampleSetDistribution; +toSampleSet: (distribution, number) => sampleSetDistribution ``` **Examples** ```javascript -toSampleSet(normal(5, 2), 1000); +toSampleSet(normal(5, 2), 1000) ``` ### truncateLeft @@ -367,7 +332,7 @@ truncateLeft: (distribution, l => number) => distribution **Examples** ```javascript -truncateLeft(normal(5, 2), 3); +truncateLeft(normal(5, 2), 3) ``` ### truncateRight @@ -381,23 +346,21 @@ truncateRight: (distribution, r => number) => distribution **Examples** ```javascript -truncateLeft(normal(5, 2), 6); +truncateLeft(normal(5, 2), 6) ``` -## Scoring - ### klDivergence -Kullback–Leibler divergence between two distributions +[Kullback–Leibler divergence](https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence) between two distributions. ```javascript -klDivergence: (distribution, distribution) => number; +klDivergence: (distribution, distribution) => number ``` **Examples** ```javascript -klDivergence(normal(5, 2), normal(5, 4)); // returns 0.57 +klDivergence(normal(5, 2), normal(5, 4)) // returns 0.57 ``` ## Display @@ -405,13 +368,13 @@ klDivergence(normal(5, 2), normal(5, 4)); // returns 0.57 ### toString ```javascript -toString: (distribution) => string; +toString: (distribution) => string ``` **Examples** ```javascript -toString(normal(5, 2)); +toString(normal(5, 2)) ``` ### toSparkline @@ -419,13 +382,13 @@ toString(normal(5, 2)); Produce a sparkline of length n ```javascript -toSparkline: (distribution, n = 20) => string; +toSparkline: (distribution, n = 20) => string ``` **Examples** ```javascript -toSparkline(normal(5, 2), 10); +toSparkline(normal(5, 2), 10) ``` ### inspect @@ -433,13 +396,13 @@ toSparkline(normal(5, 2), 10); Prints the value of the distribution to the Javascript console, then returns the distribution. ```javascript -inspect: (distribution) => distribution; +inspect: (distribution) => distribution ``` **Examples** ```javascript -inspect(normal(5, 2)); +inspect(normal(5, 2)) ``` ## Normalization @@ -449,13 +412,13 @@ inspect(normal(5, 2)); Normalize a distribution. This means scaling it appropriately so that it's cumulative sum is equal to 1. ```javascript -normalize: (distribution) => distribution; +normalize: (distribution) => distribution ``` **Examples** ```javascript -normalize(normal(5, 2)); +normalize(normal(5, 2)) ``` ### isNormalized @@ -463,13 +426,13 @@ normalize(normal(5, 2)); Check of a distribution is normalized. Most distributions are typically normalized, but there are some commands that could produce non-normalized distributions. ```javascript -isNormalized: (distribution) => bool; +isNormalized: (distribution) => bool ``` **Examples** ```javascript -isNormalized(normal(5, 2)); // returns true +isNormalized(normal(5, 2)) // returns true ``` ### integralSum @@ -477,33 +440,51 @@ isNormalized(normal(5, 2)); // returns true Get the sum of the integral of a distribution. If the distribution is normalized, this will be 1. ```javascript -integralSum: (distribution) => number; +integralSum: (distribution) => number ``` **Examples** ```javascript -integralSum(normal(5, 2)); +integralSum(normal(5, 2)) ``` -## Algebraic Operations +## Regular Arithmetic Operations + +Regular arithmetic operations cover the basic mathematical operations on distributions. They work much like their equivalent operations on numbers. + +The infixes ``+``,``-``, ``*``, ``/``, ``^``, ``-`` are supported for addition, subtraction, multiplication, division, power, and unaryMinus. + +```javascript +pointMass(5 + 10) == pointMass(5) + pointMass(10) +``` ### add ```javascript -add: (distributionLike, distributionLike) => distribution; +add: (distributionLike, distributionLike) => distribution +``` + +```javascript +normal(0,1) + normal(1,3) // returns normal(1, 3.16...) +add(normal(0,1), normal(1,3)) // returns normal(1, 3.16...) ``` ### sum +**Todo: Not yet implemented for distributions** ```javascript sum: (list) => distribution ``` +```javascript +sum([normal(0,1), normal(1,3), uniform(10,1)]) +``` + ### multiply ```javascript -multiply: (distributionLike, distributionLike) => distribution; +multiply: (distributionLike, distributionLike) => distribution ``` ### product @@ -515,118 +496,123 @@ product: (list) => distribution ### subtract ```javascript -subtract: (distributionLike, distributionLike) => distribution; +subtract: (distributionLike, distributionLike) => distribution ``` ### divide ```javascript -divide: (distributionLike, distributionLike) => distribution; +divide: (distributionLike, distributionLike) => distribution ``` ### pow ```javascript -pow: (distributionLike, distributionLike) => distribution; +pow: (distributionLike, distributionLike) => distribution ``` ### exp ```javascript -exp: (distributionLike, distributionLike) => distribution; +exp: (distributionLike, distributionLike) => distribution ``` ### log ```javascript -log: (distributionLike, distributionLike) => distribution; +log: (distributionLike, distributionLike) => distribution ``` ### log10 ```javascript -log10: (distributionLike, distributionLike) => distribution; +log10: (distributionLike, distributionLike) => distribution ``` ### unaryMinus ```javascript -unaryMinus: (distribution) => distribution; +unaryMinus: (distribution) => distribution ``` -## Pointwise Operations +```javascript +-(normal(5,2)) // same as normal(-5, 2) +unaryMinus(normal(5,2)) // same as normal(-5, 2) +``` + +## Pointwise Arithmetic Operations ### dotAdd ```javascript -dotAdd: (distributionLike, distributionLike) => distribution; +dotAdd: (distributionLike, distributionLike) => distribution ``` ### dotMultiply ```javascript -dotMultiply: (distributionLike, distributionLike) => distribution; +dotMultiply: (distributionLike, distributionLike) => distribution ``` ### dotSubtract ```javascript -dotSubtract: (distributionLike, distributionLike) => distribution; +dotSubtract: (distributionLike, distributionLike) => distribution ``` ### dotDivide ```javascript -dotDivide: (distributionLike, distributionLike) => distribution; +dotDivide: (distributionLike, distributionLike) => distribution ``` ### dotPow ```javascript -dotPow: (distributionLike, distributionLike) => distribution; +dotPow: (distributionLike, distributionLike) => distribution ``` ### dotExp ```javascript -dotExp: (distributionLike, distributionLike) => distribution; +dotExp: (distributionLike, distributionLike) => distribution ``` -## Scale Operations +## Scale Arithmetic Operations ### scaleMultiply ```javascript -scaleMultiply: (distributionLike, number) => distribution; +scaleMultiply: (distributionLike, number) => distribution ``` ### scalePow ```javascript -scalePow: (distributionLike, number) => distribution; +scalePow: (distributionLike, number) => distribution ``` ### scaleExp ```javascript -scaleExp: (distributionLike, number) => distribution; +scaleExp: (distributionLike, number) => distribution ``` ### scaleLog ```javascript -scaleLog: (distributionLike, number) => distribution; +scaleLog: (distributionLike, number) => distribution ``` ### scaleLog10 ```javascript -scaleLog10: (distributionLike, number) => distribution; +scaleLog10: (distributionLike, number) => distribution ``` ## Special -### Declaration (Continuous Function) +### Declaration (Continuous Functions) Adds metadata to a function of the input ranges. Works now for numeric and date inputs. This is useful when making predictions. It allows you to limit the domain that your prediction will be used and scored within. diff --git a/packages/website/docs/Api/DistPointSet.md b/packages/website/docs/Api/DistPointSet.md index bf65ad68..6e2eea26 100644 --- a/packages/website/docs/Api/DistPointSet.md +++ b/packages/website/docs/Api/DistPointSet.md @@ -5,18 +5,46 @@ title: Point Set Distribution ### make +Converts the distribution in question into a point set distribution. If the distribution is symbolic, then it does this by taking the quantiles. If the distribution is a sample set, then it uses a version of kernel density estimation to approximate the point set format. One complication of this latter process is that if there is a high proportion of overlapping samples (samples that are exactly the same as each other), it will convert these samples into discrete point masses. Eventually we'd like to add further methods to help adjust this process. + + ``` PointSet.make: (distribution) => pointSetDist ``` ### makeContinuous +**TODO: Now called "toContinuousPointSet"** + +Converts a set of x-y coordinates directly into a continuous distribution. + ``` PointSet.makeContinuous: (list<{x: number, y: number}>) => pointSetDist ``` +```javascript +PointSet.makeContinuous([ + { x: 0, y: 0.1 }, + { x: 1, y: 0.2 }, + { x: 2, y: 0.15 }, + { x: 3, y: 0.1 }, +]) +``` + ### makeDiscrete +**TODO: Now called "toDiscretePointSet"** + +Converts a set of x-y coordinates directly into a discrete distribution. ``` PointSet.makeDiscrete: (list<{x: number, y: number}>) => pointSetDist ``` + +```javascript +toDiscretePointSet([ + { x: 0, y: 0.1 }, + { x: 1, y: 0.2 }, + { x: 2, y: 0.15 }, + { x: 3, y: 0.1 }, +]) +``` diff --git a/packages/website/docs/Api/Duration.mdx b/packages/website/docs/Api/Duration.mdx index 6f81a352..ba25fcbf 100644 --- a/packages/website/docs/Api/Duration.mdx +++ b/packages/website/docs/Api/Duration.mdx @@ -3,6 +3,10 @@ sidebar_position: 6 title: Duration --- +Duration works with the [Date](/docs/Api/Date) type. Similar to the Date implementation, the Duration functions are early and experimental. There is no support yet for date or duration probability distributions. + +Durations are stored in Unix milliseconds. + import TOCInline from "@theme/TOCInline"; diff --git a/packages/website/docs/Guides/Distributions.mdx b/packages/website/docs/Guides/DistributionCreation.mdx similarity index 95% rename from packages/website/docs/Guides/Distributions.mdx rename to packages/website/docs/Guides/DistributionCreation.mdx index 2688f398..3dae8166 100644 --- a/packages/website/docs/Guides/Distributions.mdx +++ b/packages/website/docs/Guides/DistributionCreation.mdx @@ -91,7 +91,7 @@ The `mixture` mixes combines multiple distributions to create a mixture. You can ### Arguments -- `distributions`: A set of distributions or numbers, each passed as a paramater. Numbers will be converted into Delta distributions. +- `distributions`: A set of distributions or numbers, each passed as a paramater. Numbers will be converted into point mass distributions. - `weights`: An optional array of numbers, each representing the weight of its corresponding distribution. The weights will be re-scaled to add to `1.0`. If a weights array is provided, it must be the same length as the distribution paramaters. ### Aliases @@ -221,22 +221,22 @@ Creates a [uniform distribution]( -## Delta +## Point Mass -`delta(value:number)` +`pointMass(value:number)` Creates a discrete distribution with all of its probability mass at point `value`. -Few Squiggle users call the function `delta()` directly. Numbers are converted into delta distributions automatically, when it is appropriate. +Few Squiggle users call the function `pointMass()` directly. Numbers are converted into point mass distributions automatically, when it is appropriate. -For example, in the function `mixture(1,2,normal(5,2))`, the first two arguments will get converted into delta distributions -with values at 1 and 2. Therefore, this is the same as `mixture(delta(1),delta(2),normal(5,2))`. +For example, in the function `mixture(1,2,normal(5,2))`, the first two arguments will get converted into point mass distributions +with values at 1 and 2. Therefore, this is the same as `mixture(pointMass(1),pointMass(2),pointMass(5,2))`. -`Delta()` distributions are currently the only discrete distributions accessible in Squiggle. +`pointMass()` distributions are currently the only discrete distributions accessible in Squiggle. - - + + diff --git a/packages/website/docs/Guides/Functions.mdx b/packages/website/docs/Guides/Functions.mdx index f225252a..4cd32f37 100644 --- a/packages/website/docs/Guides/Functions.mdx +++ b/packages/website/docs/Guides/Functions.mdx @@ -170,7 +170,7 @@ given point x. ### Cumulative density function The `cdf(dist, x)` gives the cumulative probability of the distribution -or all values lower than x. It is the inverse of `inv`. +or all values lower than x. It is the inverse of `quantile`. @@ -179,13 +179,13 @@ or all values lower than x. It is the inverse of `inv`. - `x` must be a scalar - `dist` must be a distribution -### Inverse CDF +### Quantile -The `inv(dist, prob)` gives the value x or which the probability for all values +The `quantile(dist, prob)` gives the value x or which the probability for all values lower than x is equal to prob. It is the inverse of `cdf`. In the literature, it is also known as the quantiles function. - + #### Validity diff --git a/packages/website/docs/Internal/Invariants.md b/packages/website/docs/Internal/Invariants.md index 91adf1a1..1e501664 100644 --- a/packages/website/docs/Internal/Invariants.md +++ b/packages/website/docs/Internal/Invariants.md @@ -122,14 +122,14 @@ TODO TODO -## `pdf`, `cdf`, and `inv` +## `pdf`, `cdf`, and `quantile` -With $\forall dist, pdf := x \mapsto \texttt{pdf}(dist, x) \land cdf := x \mapsto \texttt{cdf}(dist, x) \land inv := p \mapsto \texttt{inv}(dist, p)$, +With $\forall dist, pdf := x \mapsto \texttt{pdf}(dist, x) \land cdf := x \mapsto \texttt{cdf}(dist, x) \land quantile := p \mapsto \texttt{quantile}(dist, p)$, -### `cdf` and `inv` are inverses +### `cdf` and `quantile` are inverses $$ -\forall x \in (0,1), cdf(inv(x)) = x \land \forall x \in \texttt{dom}(cdf), x = inv(cdf(x)) +\forall x \in (0,1), cdf(quantile(x)) = x \land \forall x \in \texttt{dom}(cdf), x = quantile(cdf(x)) $$ ### The codomain of `cdf` equals the open interval `(0,1)` equals the codomain of `pdf` diff --git a/packages/website/docs/Internal/Processing-Confidence-Intervals.md b/packages/website/docs/Internal/Processing-Confidence-Intervals.md index 01afeb79..e1dc6e47 100644 --- a/packages/website/docs/Internal/Processing-Confidence-Intervals.md +++ b/packages/website/docs/Internal/Processing-Confidence-Intervals.md @@ -25,7 +25,7 @@ $$ a \cdot Normal(\mu, \sigma) = Normal(a \cdot \mu, |a| \cdot \sigma) $$ -We can now look at the inverse cdf of a $Normal(0,1)$. We find that the 95% point is reached at $1.6448536269514722$. ([source](https://stackoverflow.com/questions/20626994/how-to-calculate-the-inverse-of-the-normal-cumulative-distribution-function-in-p)) This means that the 90% confidence interval is $[-1.6448536269514722, 1.6448536269514722]$, which has a width of $2 \cdot 1.6448536269514722$. +We can now look at the quantile of a $Normal(0,1)$. We find that the 95% point is reached at $1.6448536269514722$. ([source](https://stackoverflow.com/questions/20626994/how-to-calculate-the-inverse-of-the-normal-cumulative-distribution-function-in-p)) This means that the 90% confidence interval is $[-1.6448536269514722, 1.6448536269514722]$, which has a width of $2 \cdot 1.6448536269514722$. So then, if we take a $Normal(0,1)$ and we multiply it by $\frac{(high -. low)}{(2. *. 1.6448536269514722)}$, it's 90% confidence interval will be multiplied by the same amount. Then we just have to shift it by the mean to get our target normal. diff --git a/packages/website/docusaurus.config.js b/packages/website/docusaurus.config.js index 4152ae6e..68baf7c8 100644 --- a/packages/website/docusaurus.config.js +++ b/packages/website/docusaurus.config.js @@ -66,7 +66,7 @@ const config = { }, { type: "doc", - docId: "Api/Dictionary", + docId: "Api/DistGeneric", position: "left", label: "API", }, From bea4e13cd315e895ac06c1d859cbf6cf639f7b5b Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sun, 12 Jun 2022 21:33:40 -0700 Subject: [PATCH 02/19] Minor cleanup on distributions --- packages/website/docs/Api/DistGeneric.mdx | 89 +++++++++++++---------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/packages/website/docs/Api/DistGeneric.mdx b/packages/website/docs/Api/DistGeneric.mdx index 4e91543c..93833f3e 100644 --- a/packages/website/docs/Api/DistGeneric.mdx +++ b/packages/website/docs/Api/DistGeneric.mdx @@ -19,7 +19,7 @@ These are functions for creating primative distributions. Many of these could op See a longer tutorial on creating distributions [here](/docs/Guides/DistributionCreation). -### Normal +### normal **Definitions** @@ -39,7 +39,7 @@ normal(5 to 10, normal(3, 2)) normal({ mean: uniform(5, 9), stdev: 3 }) ``` -### Lognormal +### lognormal **Definitions** @@ -57,7 +57,7 @@ lognormal({ p5: 4, p95: 10 }) lognormal({ mean: 5, stdev: 2 }) ``` -### Uniform +### uniform **Definitions** @@ -71,7 +71,7 @@ uniform: (distribution|number, distribution|number) => distribution uniform(10, 12) ``` -### Beta +### beta **Definitions** @@ -85,7 +85,7 @@ beta: (distribution|number, distribution|number) => distribution beta(20, 25) ``` -### Cauchy +### cauchy **Definitions** @@ -99,7 +99,7 @@ cauchy: (distribution|number, distribution|number) => distribution cauchy(5, 1) ``` -### Gamma +### gamma **Definitions** @@ -127,13 +127,55 @@ logistic: (distribution|number, distribution|number) => distribution gamma(5, 1) ``` -### To (Distribution) +### exponential + +**Definitions** + +```javascript +exponential: (distribution|number) => distribution +``` + +**Examples** + +```javascript +exponential(2) +``` + +### bernoulli + +**Definitions** + +```javascript +bernoulli: (distribution|number) => distribution +``` + +**Examples** + +```javascript +bernoulli(0.5) +``` + +### triangular + +**Definitions** + +```javascript +triangular: (number, number, number) => distribution +``` + +**Examples** + +```javascript +triangular(5, 10, 20) +``` + +### To / credibleIntervalToDistribution The `to` function is an easy way to generate simple distributions using predicted _5th_ and _95th_ percentiles. If both values are above zero, a `lognormal` distribution is used. If not, a `normal` distribution is used. -**Definitions** +``To`` is an alias for ``credibleIntervalToDistribution``. However, because of its frequent use, it is recommended to use the shorter name. ```javascript to: (distribution|number, distribution|number) => distribution @@ -148,35 +190,6 @@ to(5,10) -5 to 5 ``` -### Exponential - -**Definitions** - -```javascript -exponential: (distribution|number) => distribution -``` - -**Examples** - -```javascript -exponential(2) -``` - -### Bernoulli - -**Definitions** - -```javascript -bernoulli: (distribution|number) => distribution -``` - -**Examples** - -```javascript -bernoulli(0.5) -``` - -## Functions ### mixture @@ -193,6 +206,8 @@ mx(normal(5, 1), normal(10, 1), [0.3, 0.7]) mx([normal(5, 1), normal(10, 1)], [0.3, 0.7]) ``` +## Functions + ### sample One random sample from the distribution From 5f26ac95329aa89ccf4749399a83a3ce0ca11df0 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Sun, 12 Jun 2022 21:42:52 -0700 Subject: [PATCH 03/19] Removed the definitions tags in documentation --- packages/website/docs/Api/DistGeneric.mdx | 137 ++++++++++------------ packages/website/docs/Api/DistPointSet.md | 2 +- 2 files changed, 64 insertions(+), 75 deletions(-) diff --git a/packages/website/docs/Api/DistGeneric.mdx b/packages/website/docs/Api/DistGeneric.mdx index 93833f3e..47927116 100644 --- a/packages/website/docs/Api/DistGeneric.mdx +++ b/packages/website/docs/Api/DistGeneric.mdx @@ -21,9 +21,7 @@ See a longer tutorial on creating distributions [here](/docs/Guides/Distribution ### normal -**Definitions** - -```javascript +``` normal: (distribution|number, distribution|number) => distribution normal: (dict<{p5: distribution|number, p95: distribution|number}>) => distribution normal: (dict<{mean: distribution|number, stdev: distribution|number}>) => distribution @@ -41,9 +39,7 @@ normal({ mean: uniform(5, 9), stdev: 3 }) ### lognormal -**Definitions** - -```javascript +``` lognormal: (distribution|number, distribution|number) => distribution lognormal: (dict<{p5: distribution|number, p95: distribution|number}>) => distribution lognormal: (dict<{mean: distribution|number, stdev: distribution|number}>) => distribution @@ -59,9 +55,7 @@ lognormal({ mean: 5, stdev: 2 }) ### uniform -**Definitions** - -```javascript +``` uniform: (distribution|number, distribution|number) => distribution ``` @@ -73,9 +67,7 @@ uniform(10, 12) ### beta -**Definitions** - -```javascript +``` beta: (distribution|number, distribution|number) => distribution ``` @@ -87,9 +79,7 @@ beta(20, 25) ### cauchy -**Definitions** - -```javascript +``` cauchy: (distribution|number, distribution|number) => distribution ``` @@ -101,8 +91,6 @@ cauchy(5, 1) ### gamma -**Definitions** - ```javascript gamma: (distribution|number, distribution|number) => distribution ``` @@ -115,9 +103,7 @@ gamma(5, 1) ### Logistic -**Definitions** - -```javascript +``` logistic: (distribution|number, distribution|number) => distribution ``` @@ -129,9 +115,7 @@ gamma(5, 1) ### exponential -**Definitions** - -```javascript +``` exponential: (distribution|number) => distribution ``` @@ -143,9 +127,7 @@ exponential(2) ### bernoulli -**Definitions** - -```javascript +``` bernoulli: (distribution|number) => distribution ``` @@ -157,8 +139,6 @@ bernoulli(0.5) ### triangular -**Definitions** - ```javascript triangular: (number, number, number) => distribution ``` @@ -177,7 +157,7 @@ If both values are above zero, a `lognormal` distribution is used. If not, a `no ``To`` is an alias for ``credibleIntervalToDistribution``. However, because of its frequent use, it is recommended to use the shorter name. -```javascript +``` to: (distribution|number, distribution|number) => distribution credibleIntervalToDistribution(distribution|number, distribution|number) => distribution ``` @@ -193,7 +173,7 @@ to(5,10) ### mixture -```javascript +``` mixture: (...distributionLike, weights?:list) => distribution mixture: (list, weights?:list) => distribution ``` @@ -212,8 +192,8 @@ mx([normal(5, 1), normal(10, 1)], [0.3, 0.7]) One random sample from the distribution -```javascript -sample(distribution) => number +``` +sample: (distribution) => number ``` **Examples** @@ -226,7 +206,7 @@ sample(normal(5, 2)) N random samples from the distribution -```javascript +``` sampleN: (distribution, number) => list ``` @@ -240,7 +220,7 @@ sampleN(normal(5, 2), 100) The distribution mean -```javascript +``` mean: (distribution) => number ``` @@ -254,7 +234,7 @@ mean(normal(5, 2)) Standard deviation. Only works now on sample set distributions (so converts other distributions into sample set in order to calculate.) -```javascript +``` stdev: (distribution) => number ``` @@ -262,19 +242,19 @@ stdev: (distribution) => number Variance. Similar to stdev, only works now on sample set distributions. -```javascript +``` variance: (distribution) => number ``` ### mode -```javascript +``` mode: (distribution) => number ``` ### cdf -```javascript +``` cdf: (distribution, number) => number ``` @@ -286,7 +266,7 @@ cdf(normal(5, 2), 3) ### pdf -```javascript +``` pdf: (distribution, number) => number ``` @@ -298,7 +278,7 @@ pdf(normal(5, 2), 3) ### quantile -```javascript +``` quantile: (distribution, number) => number ``` @@ -310,9 +290,11 @@ quantile(normal(5, 2), 0.5) ### toPointSet +**TODO: Will soon be called "PointSet.make"** + Converts a distribution to the pointSet format -```javascript +``` toPointSet: (distribution) => pointSetDistribution ``` @@ -323,10 +305,11 @@ toPointSet(normal(5, 2)) ``` ### toSampleSet +**TODO: Will soon be called "SampleSet.make"** Converts a distribution to the sampleSet format, with n samples -```javascript +``` toSampleSet: (distribution, number) => sampleSetDistribution ``` @@ -340,7 +323,7 @@ toSampleSet(normal(5, 2), 1000) Truncates the left side of a distribution. Returns either a pointSet distribution or a symbolic distribution. -```javascript +``` truncateLeft: (distribution, l => number) => distribution ``` @@ -354,7 +337,7 @@ truncateLeft(normal(5, 2), 3) Truncates the right side of a distribution. Returns either a pointSet distribution or a symbolic distribution. -```javascript +``` truncateRight: (distribution, r => number) => distribution ``` @@ -368,7 +351,7 @@ truncateLeft(normal(5, 2), 6) [Kullback–Leibler divergence](https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence) between two distributions. -```javascript +``` klDivergence: (distribution, distribution) => number ``` @@ -382,7 +365,7 @@ klDivergence(normal(5, 2), normal(5, 4)) // returns 0.57 ### toString -```javascript +``` toString: (distribution) => string ``` @@ -396,7 +379,7 @@ toString(normal(5, 2)) Produce a sparkline of length n -```javascript +``` toSparkline: (distribution, n = 20) => string ``` @@ -410,7 +393,7 @@ toSparkline(normal(5, 2), 10) Prints the value of the distribution to the Javascript console, then returns the distribution. -```javascript +``` inspect: (distribution) => distribution ``` @@ -426,7 +409,7 @@ inspect(normal(5, 2)) Normalize a distribution. This means scaling it appropriately so that it's cumulative sum is equal to 1. -```javascript +``` normalize: (distribution) => distribution ``` @@ -440,7 +423,7 @@ normalize(normal(5, 2)) Check of a distribution is normalized. Most distributions are typically normalized, but there are some commands that could produce non-normalized distributions. -```javascript +``` isNormalized: (distribution) => bool ``` @@ -454,7 +437,7 @@ isNormalized(normal(5, 2)) // returns true Get the sum of the integral of a distribution. If the distribution is normalized, this will be 1. -```javascript +``` integralSum: (distribution) => number ``` @@ -476,10 +459,12 @@ pointMass(5 + 10) == pointMass(5) + pointMass(10) ### add -```javascript +``` add: (distributionLike, distributionLike) => distribution ``` +**Examples** + ```javascript normal(0,1) + normal(1,3) // returns normal(1, 3.16...) add(normal(0,1), normal(1,3)) // returns normal(1, 3.16...) @@ -488,68 +473,72 @@ add(normal(0,1), normal(1,3)) // returns normal(1, 3.16...) ### sum **Todo: Not yet implemented for distributions** -```javascript +``` sum: (list) => distribution ``` +**Examples** + ```javascript sum([normal(0,1), normal(1,3), uniform(10,1)]) ``` ### multiply -```javascript +``` multiply: (distributionLike, distributionLike) => distribution ``` ### product -```javascript +``` product: (list) => distribution ``` ### subtract -```javascript +``` subtract: (distributionLike, distributionLike) => distribution ``` ### divide -```javascript +``` divide: (distributionLike, distributionLike) => distribution ``` ### pow -```javascript +``` pow: (distributionLike, distributionLike) => distribution ``` ### exp -```javascript +``` exp: (distributionLike, distributionLike) => distribution ``` ### log -```javascript +``` log: (distributionLike, distributionLike) => distribution ``` ### log10 -```javascript +``` log10: (distributionLike, distributionLike) => distribution ``` ### unaryMinus -```javascript +``` unaryMinus: (distribution) => distribution ``` +**Examples** + ```javascript -(normal(5,2)) // same as normal(-5, 2) unaryMinus(normal(5,2)) // same as normal(-5, 2) @@ -559,37 +548,37 @@ unaryMinus(normal(5,2)) // same as normal(-5, 2) ### dotAdd -```javascript +``` dotAdd: (distributionLike, distributionLike) => distribution ``` ### dotMultiply -```javascript +``` dotMultiply: (distributionLike, distributionLike) => distribution ``` ### dotSubtract -```javascript +``` dotSubtract: (distributionLike, distributionLike) => distribution ``` ### dotDivide -```javascript +``` dotDivide: (distributionLike, distributionLike) => distribution ``` ### dotPow -```javascript +``` dotPow: (distributionLike, distributionLike) => distribution ``` ### dotExp -```javascript +``` dotExp: (distributionLike, distributionLike) => distribution ``` @@ -597,31 +586,31 @@ dotExp: (distributionLike, distributionLike) => distribution ### scaleMultiply -```javascript +``` scaleMultiply: (distributionLike, number) => distribution ``` ### scalePow -```javascript +``` scalePow: (distributionLike, number) => distribution ``` ### scaleExp -```javascript +``` scaleExp: (distributionLike, number) => distribution ``` ### scaleLog -```javascript +``` scaleLog: (distributionLike, number) => distribution ``` ### scaleLog10 -```javascript +``` scaleLog10: (distributionLike, number) => distribution ``` @@ -631,7 +620,7 @@ scaleLog10: (distributionLike, number) => distribution Adds metadata to a function of the input ranges. Works now for numeric and date inputs. This is useful when making predictions. It allows you to limit the domain that your prediction will be used and scored within. -```javascript +``` declareFn: (dict<{fn: lambda, inputs: array>}>) => declaration ``` diff --git a/packages/website/docs/Api/DistPointSet.md b/packages/website/docs/Api/DistPointSet.md index 6e2eea26..eb3f8b93 100644 --- a/packages/website/docs/Api/DistPointSet.md +++ b/packages/website/docs/Api/DistPointSet.md @@ -41,7 +41,7 @@ PointSet.makeDiscrete: (list<{x: number, y: number}>) => pointSetDist ``` ```javascript -toDiscretePointSet([ +PointSet.makeDiscrete([ { x: 0, y: 0.1 }, { x: 1, y: 0.2 }, { x: 2, y: 0.15 }, From 2dc71315ef4999fcd66935a71e120f77e2dd748a Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Mon, 13 Jun 2022 11:43:26 -0700 Subject: [PATCH 04/19] Added key math variables, all lowercase --- .../SquiggleLibrary/SquiggleLibrary_Math.res | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/SquiggleLibrary/SquiggleLibrary_Math.res b/packages/squiggle-lang/src/rescript/SquiggleLibrary/SquiggleLibrary_Math.res index a29fafcc..0e07337c 100644 --- a/packages/squiggle-lang/src/rescript/SquiggleLibrary/SquiggleLibrary_Math.res +++ b/packages/squiggle-lang/src/rescript/SquiggleLibrary/SquiggleLibrary_Math.res @@ -1,8 +1,23 @@ module Bindings = Reducer_Category_Bindings module Module = Reducer_Category_Module -let m = - Module.emptyModule->Module.defineNumber("pi", Js.Math._PI)->Module.defineNumber("e", Js.Math._E) +let availableNumbers: array<(string, float)> = [ + ("pi", Js.Math._PI), + ("e", Js.Math._E), + ("ln2", Js.Math._LN2), + ("ln10", Js.Math._LN10), + ("log2e", Js.Math._LOG2E), + ("log10e", Js.Math._LOG10E), + ("sqrt2", Js.Math._SQRT2), + ("sqrt1_2", Js.Math._SQRT1_2), + ("phi", 1.618033988749895), + ("tau", 6.283185307179586), +] + +let mathBindings: Bindings.ExpressionT.bindings = + availableNumbers + ->E.A2.fmap(((name, v)) => (name, ReducerInterface_ExpressionValue.EvNumber(v))) + ->Belt.Map.String.fromArray let makeBindings = (previousBindings: Bindings.t): Bindings.t => - previousBindings->Bindings.defineModule("Math", m) + previousBindings->Bindings.defineModule("Math", mathBindings) From 6a4132c955c344153ca0617ee7c962bd3bfa7db4 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Mon, 13 Jun 2022 12:10:24 -0700 Subject: [PATCH 05/19] Ran format --- .../ReducerInterface_GenericDistribution.res | 3 ++- packages/website/docs/Api/Date.md | 3 ++- packages/website/docs/Api/Dictionary.md | 1 + packages/website/docs/Api/DistGeneric.mdx | 27 ++++++++++--------- packages/website/docs/Api/DistPointSet.md | 6 ++--- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index 6d98d724..66ee915c 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -273,7 +273,8 @@ let dispatchToGenericOutput = ( | ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist, ~env) | ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist, ~env) | ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env) - | ("quantile", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist, ~env) + | ("quantile", [EvDistribution(dist), EvNumber(float)]) => + Helpers.toFloatFn(#Inv(float), dist, ~env) | ("toSampleSet", [EvDistribution(dist), EvNumber(float)]) => Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist, ~env) | ("toSampleSet", [EvDistribution(dist)]) => diff --git a/packages/website/docs/Api/Date.md b/packages/website/docs/Api/Date.md index deccdad3..9f9b9f09 100644 --- a/packages/website/docs/Api/Date.md +++ b/packages/website/docs/Api/Date.md @@ -6,7 +6,8 @@ title: Date Squiggle date types are a very simple implementation on [Javascript's Date type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date). It's mainly here for early experimentation. There are more relevant functions for the [Duration](/docs/Api/Duration) type. ### makeFromYear -(Now ``makeDateFromYear``) + +(Now `makeDateFromYear`) ``` Date.makeFromYear: (number) => date diff --git a/packages/website/docs/Api/Dictionary.md b/packages/website/docs/Api/Dictionary.md index 0152f122..0e6dfd17 100644 --- a/packages/website/docs/Api/Dictionary.md +++ b/packages/website/docs/Api/Dictionary.md @@ -8,6 +8,7 @@ Squiggle dictionaries work similar to Python dictionaries. The syntax is similar Dictionaries are unordered and duplicates are not allowed. They are meant to be immutable, like most types in Squiggle. **Example** + ```javascript valueFromOfficeItems = { keyboard: 1, diff --git a/packages/website/docs/Api/DistGeneric.mdx b/packages/website/docs/Api/DistGeneric.mdx index 47927116..65e727ee 100644 --- a/packages/website/docs/Api/DistGeneric.mdx +++ b/packages/website/docs/Api/DistGeneric.mdx @@ -3,10 +3,10 @@ sidebar_position: 3 title: Distribution --- -Distributions are the flagship data type in Squiggle. The distribution type is a generic data type that contains one of three different formats of distributions. -These subtypes are [point set](/docs/Api/DistPointSet), [sample set](/docs/Api/DistSampleSet), and symbolic. The first two of these have a few custom functions that only work on them. You can read more about the differences between these formats [here](/docs/Discussions/Three-Formats-Of-Distributions). +Distributions are the flagship data type in Squiggle. The distribution type is a generic data type that contains one of three different formats of distributions. +These subtypes are [point set](/docs/Api/DistPointSet), [sample set](/docs/Api/DistSampleSet), and symbolic. The first two of these have a few custom functions that only work on them. You can read more about the differences between these formats [here](/docs/Discussions/Three-Formats-Of-Distributions). -Several functions below only can work on particular distribution formats. +Several functions below only can work on particular distribution formats. For example, scoring and pointwise math requires the point set format. When this happens, the types are automatically converted to the correct format. These conversions are lossy. import TOCInline from "@theme/TOCInline" @@ -15,7 +15,7 @@ import TOCInline from "@theme/TOCInline" ## Distribution Creation -These are functions for creating primative distributions. Many of these could optionally take in distributions as inputs; in these cases, Monte Carlo Sampling will be used to generate the greater distribution. This can be used for simple hierarchical models. +These are functions for creating primative distributions. Many of these could optionally take in distributions as inputs. In these cases, Monte Carlo Sampling will be used to generate the greater distribution. This can be used for simple hierarchical models. See a longer tutorial on creating distributions [here](/docs/Guides/DistributionCreation). @@ -155,7 +155,7 @@ The `to` function is an easy way to generate simple distributions using predicte If both values are above zero, a `lognormal` distribution is used. If not, a `normal` distribution is used. -``To`` is an alias for ``credibleIntervalToDistribution``. However, because of its frequent use, it is recommended to use the shorter name. +`To` is an alias for `credibleIntervalToDistribution`. However, because of its frequent use, it is recommended to use the shorter name. ``` to: (distribution|number, distribution|number) => distribution @@ -170,7 +170,6 @@ to(5,10) -5 to 5 ``` - ### mixture ``` @@ -239,8 +238,8 @@ stdev: (distribution) => number ``` ### variance -Variance. Similar to stdev, only works now on sample set distributions. +Variance. Similar to stdev, only works now on sample set distributions. ``` variance: (distribution) => number @@ -305,6 +304,7 @@ toPointSet(normal(5, 2)) ``` ### toSampleSet + **TODO: Will soon be called "SampleSet.make"** Converts a distribution to the sampleSet format, with n samples @@ -451,7 +451,7 @@ integralSum(normal(5, 2)) Regular arithmetic operations cover the basic mathematical operations on distributions. They work much like their equivalent operations on numbers. -The infixes ``+``,``-``, ``*``, ``/``, ``^``, ``-`` are supported for addition, subtraction, multiplication, division, power, and unaryMinus. +The infixes `+`,`-`, `*`, `/`, `^`, `-` are supported for addition, subtraction, multiplication, division, power, and unaryMinus. ```javascript pointMass(5 + 10) == pointMass(5) + pointMass(10) @@ -466,11 +466,12 @@ add: (distributionLike, distributionLike) => distribution **Examples** ```javascript -normal(0,1) + normal(1,3) // returns normal(1, 3.16...) -add(normal(0,1), normal(1,3)) // returns normal(1, 3.16...) +normal(0, 1) + normal(1, 3) // returns normal(1, 3.16...) +add(normal(0, 1), normal(1, 3)) // returns normal(1, 3.16...) ``` ### sum + **Todo: Not yet implemented for distributions** ``` @@ -480,7 +481,7 @@ sum: (list) => distribution **Examples** ```javascript -sum([normal(0,1), normal(1,3), uniform(10,1)]) +sum([normal(0, 1), normal(1, 3), uniform(10, 1)]) ``` ### multiply @@ -540,8 +541,8 @@ unaryMinus: (distribution) => distribution **Examples** ```javascript --(normal(5,2)) // same as normal(-5, 2) -unaryMinus(normal(5,2)) // same as normal(-5, 2) +-normal(5, 2) // same as normal(-5, 2) +unaryMinus(normal(5, 2)) // same as normal(-5, 2) ``` ## Pointwise Arithmetic Operations diff --git a/packages/website/docs/Api/DistPointSet.md b/packages/website/docs/Api/DistPointSet.md index eb3f8b93..6fabd158 100644 --- a/packages/website/docs/Api/DistPointSet.md +++ b/packages/website/docs/Api/DistPointSet.md @@ -7,7 +7,6 @@ title: Point Set Distribution Converts the distribution in question into a point set distribution. If the distribution is symbolic, then it does this by taking the quantiles. If the distribution is a sample set, then it uses a version of kernel density estimation to approximate the point set format. One complication of this latter process is that if there is a high proportion of overlapping samples (samples that are exactly the same as each other), it will convert these samples into discrete point masses. Eventually we'd like to add further methods to help adjust this process. - ``` PointSet.make: (distribution) => pointSetDist ``` @@ -28,10 +27,11 @@ PointSet.makeContinuous([ { x: 1, y: 0.2 }, { x: 2, y: 0.15 }, { x: 3, y: 0.1 }, -]) +]); ``` ### makeDiscrete + **TODO: Now called "toDiscretePointSet"** Converts a set of x-y coordinates directly into a discrete distribution. @@ -46,5 +46,5 @@ PointSet.makeDiscrete([ { x: 1, y: 0.2 }, { x: 2, y: 0.15 }, { x: 3, y: 0.1 }, -]) +]); ``` From 62ed997de2a60aea903ecd8161fb63acd2718fc0 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Mon, 13 Jun 2022 18:13:43 -0700 Subject: [PATCH 06/19] More progress on DistGeneric --- .../Distributions/DistributionTypes.res | 2 +- .../SymbolicDist/SymbolicDist.res | 2 +- .../ReducerInterface_GenericDistribution.res | 4 +- packages/website/docs/Api/DistGeneric.mdx | 142 +++++++++++------- packages/website/docs/Api/Math.md | 20 +-- packages/website/docs/Api/Number.mdx | 66 ++++---- 6 files changed, 135 insertions(+), 101 deletions(-) diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res index a6eb0431..cdb0ee3d 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res @@ -142,7 +142,7 @@ module DistributionOperation = { | ToDist(Scale(#LogarithmWithThreshold(eps), r)) => `scaleLogWithThreshold(${E.Float.toFixed(r)}, epsilon=${E.Float.toFixed(eps)})` | ToString(ToString) => `toString` - | ToString(ToSparkline(n)) => `toSparkline(${E.I.toString(n)})` + | ToString(ToSparkline(n)) => `sparkline(${E.I.toString(n)})` | ToBool(IsNormalized) => `isNormalized` | ToDistCombination(Algebraic(_), _, _) => `algebraic` | ToDistCombination(Pointwise, _, _) => `pointwise` diff --git a/packages/squiggle-lang/src/rescript/Distributions/SymbolicDist/SymbolicDist.res b/packages/squiggle-lang/src/rescript/Distributions/SymbolicDist/SymbolicDist.res index ff29bc65..f33fc450 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/SymbolicDist/SymbolicDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/SymbolicDist/SymbolicDist.res @@ -295,7 +295,7 @@ module Float = { let inv = (p, t: t) => p < t ? 0.0 : 1.0 let mean = (t: t) => Ok(t) let sample = (t: t) => t - let toString = (t: t) => j`Delta($t)` + let toString = (t: t) => j`PointMass($t)` let toPointSetDist = (t: t): PointSetTypes.pointSetDist => Discrete( Discrete.make(~integralSumCache=Some(1.0), {xs: [t], ys: [1.0]}), ) diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index 66ee915c..c0418df8 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -221,9 +221,9 @@ let dispatchToGenericOutput = ( } | ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist, ~env) | ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist, ~env) - | ("toSparkline", [EvDistribution(dist)]) => + | ("sparkline", [EvDistribution(dist)]) => Helpers.toStringFn(ToSparkline(MagicNumbers.Environment.sparklineLength), dist, ~env) - | ("toSparkline", [EvDistribution(dist), EvNumber(n)]) => + | ("sparkline", [EvDistribution(dist), EvNumber(n)]) => Helpers.toStringFn(ToSparkline(Belt.Float.toInt(n)), dist, ~env) | ("exp", [EvDistribution(a)]) => // https://mathjs.org/docs/reference/functions/exp.html diff --git a/packages/website/docs/Api/DistGeneric.mdx b/packages/website/docs/Api/DistGeneric.mdx index 65e727ee..b3b5025d 100644 --- a/packages/website/docs/Api/DistGeneric.mdx +++ b/packages/website/docs/Api/DistGeneric.mdx @@ -3,14 +3,15 @@ sidebar_position: 3 title: Distribution --- +import Admonition from "@theme/Admonition"; +import TOCInline from "@theme/TOCInline"; + Distributions are the flagship data type in Squiggle. The distribution type is a generic data type that contains one of three different formats of distributions. These subtypes are [point set](/docs/Api/DistPointSet), [sample set](/docs/Api/DistSampleSet), and symbolic. The first two of these have a few custom functions that only work on them. You can read more about the differences between these formats [here](/docs/Discussions/Three-Formats-Of-Distributions). Several functions below only can work on particular distribution formats. For example, scoring and pointwise math requires the point set format. When this happens, the types are automatically converted to the correct format. These conversions are lossy. -import TOCInline from "@theme/TOCInline" - ## Distribution Creation @@ -48,9 +49,9 @@ lognormal: (dict<{mean: distribution|number, stdev: distribution|number}>) => di **Examples** ```javascript -lognormal(0.5, 0.8) -lognormal({ p5: 4, p95: 10 }) -lognormal({ mean: 5, stdev: 2 }) +lognormal(0.5, 0.8); +lognormal({ p5: 4, p95: 10 }); +lognormal({ mean: 5, stdev: 2 }); ``` ### uniform @@ -62,7 +63,7 @@ uniform: (distribution|number, distribution|number) => distribution **Examples** ```javascript -uniform(10, 12) +uniform(10, 12); ``` ### beta @@ -74,7 +75,7 @@ beta: (distribution|number, distribution|number) => distribution **Examples** ```javascript -beta(20, 25) +beta(20, 25); ``` ### cauchy @@ -86,7 +87,7 @@ cauchy: (distribution|number, distribution|number) => distribution **Examples** ```javascript -cauchy(5, 1) +cauchy(5, 1); ``` ### gamma @@ -97,11 +98,11 @@ gamma: (distribution|number, distribution|number) => distribution **Examples** -```javascript -gamma(5, 1) +```js +gamma(5, 1); ``` -### Logistic +### logistic ``` logistic: (distribution|number, distribution|number) => distribution @@ -110,7 +111,7 @@ logistic: (distribution|number, distribution|number) => distribution **Examples** ```javascript -gamma(5, 1) +gamma(5, 1); ``` ### exponential @@ -122,7 +123,7 @@ exponential: (distribution|number) => distribution **Examples** ```javascript -exponential(2) +exponential(2); ``` ### bernoulli @@ -134,22 +135,22 @@ bernoulli: (distribution|number) => distribution **Examples** ```javascript -bernoulli(0.5) +bernoulli(0.5); ``` ### triangular ```javascript -triangular: (number, number, number) => distribution +triangular: (number, number, number) => distribution; ``` **Examples** ```javascript -triangular(5, 10, 20) +triangular(5, 10, 20); ``` -### To / credibleIntervalToDistribution +### to / credibleIntervalToDistribution The `to` function is an easy way to generate simple distributions using predicted _5th_ and _95th_ percentiles. @@ -180,9 +181,9 @@ mixture: (list, weights?:list) => distribution **Examples** ```javascript -mixture(normal(5, 1), normal(10, 1), 8) -mx(normal(5, 1), normal(10, 1), [0.3, 0.7]) -mx([normal(5, 1), normal(10, 1)], [0.3, 0.7]) +mixture(normal(5, 1), normal(10, 1), 8); +mx(normal(5, 1), normal(10, 1), [0.3, 0.7]); +mx([normal(5, 1), normal(10, 1)], [0.3, 0.7]); ``` ## Functions @@ -198,7 +199,7 @@ sample: (distribution) => number **Examples** ```javascript -sample(normal(5, 2)) +sample(normal(5, 2)); ``` ### sampleN @@ -212,7 +213,7 @@ sampleN: (distribution, number) => list **Examples** ```javascript -sampleN(normal(5, 2), 100) +sampleN(normal(5, 2), 100); ``` ### mean @@ -226,7 +227,7 @@ mean: (distribution) => number **Examples** ```javascript -mean(normal(5, 2)) +mean(normal(5, 2)); ``` ### stdev @@ -260,7 +261,7 @@ cdf: (distribution, number) => number **Examples** ```javascript -cdf(normal(5, 2), 3) +cdf(normal(5, 2), 3); ``` ### pdf @@ -272,7 +273,7 @@ pdf: (distribution, number) => number **Examples** ```javascript -pdf(normal(5, 2), 3) +pdf(normal(5, 2), 3); ``` ### quantile @@ -284,7 +285,7 @@ quantile: (distribution, number) => number **Examples** ```javascript -quantile(normal(5, 2), 0.5) +quantile(normal(5, 2), 0.5); ``` ### toPointSet @@ -300,7 +301,7 @@ toPointSet: (distribution) => pointSetDistribution **Examples** ```javascript -toPointSet(normal(5, 2)) +toPointSet(normal(5, 2)); ``` ### toSampleSet @@ -316,7 +317,7 @@ toSampleSet: (distribution, number) => sampleSetDistribution **Examples** ```javascript -toSampleSet(normal(5, 2), 1000) +toSampleSet(normal(5, 2), 1000); ``` ### truncateLeft @@ -330,7 +331,7 @@ truncateLeft: (distribution, l => number) => distribution **Examples** ```javascript -truncateLeft(normal(5, 2), 3) +truncateLeft(normal(5, 2), 3); ``` ### truncateRight @@ -344,7 +345,7 @@ truncateRight: (distribution, r => number) => distribution **Examples** ```javascript -truncateLeft(normal(5, 2), 6) +truncateLeft(normal(5, 2), 6); ``` ### klDivergence @@ -358,7 +359,7 @@ klDivergence: (distribution, distribution) => number **Examples** ```javascript -klDivergence(normal(5, 2), normal(5, 4)) // returns 0.57 +klDivergence(normal(5, 2), normal(5, 4)); // returns 0.57 ``` ## Display @@ -372,26 +373,26 @@ toString: (distribution) => string **Examples** ```javascript -toString(normal(5, 2)) +toString(normal(5, 2)); ``` -### toSparkline +### sparkline -Produce a sparkline of length n +Produce a sparkline of length n. For example, `▁▁▁▁▁▂▄▆▇██▇▆▄▂▁▁▁▁▁`. These can be useful for testing or quick text visualizations. ``` -toSparkline: (distribution, n = 20) => string +sparkline: (distribution, n = 20) => string ``` **Examples** ```javascript -toSparkline(normal(5, 2), 10) +toSparkline(truncateLeft(normal(5, 2), 3), 20); // produces ▁▇█████▇▅▄▃▂▂▁▁▁▁▁▁▁ ``` ### inspect -Prints the value of the distribution to the Javascript console, then returns the distribution. +Prints the value of the distribution to the Javascript console, then returns the distribution. Useful for debugging. ``` inspect: (distribution) => distribution @@ -400,11 +401,15 @@ inspect: (distribution) => distribution **Examples** ```javascript -inspect(normal(5, 2)) +inspect(normal(5, 2)); // logs "normal(5, 2)" to the javascript console and returns the distribution. ``` ## Normalization +There are some situations where computation will return unnormalized distributions. This means that their cumulative sums are not equal to 1.0. Unnormalized distributions are not valid for many relevant functions; for example, klDivergence and scoring. + +The only functions that do not return normalized distributions are the pointwise arithmetic operations and the scalewise arithmetic operations. If you use these functions, it is recommended that you consider normalizing the resulting distributions. + ### normalize Normalize a distribution. This means scaling it appropriately so that it's cumulative sum is equal to 1. @@ -416,7 +421,7 @@ normalize: (distribution) => distribution **Examples** ```javascript -normalize(normal(5, 2)) +normalize(normal(5, 2)); ``` ### isNormalized @@ -430,12 +435,14 @@ isNormalized: (distribution) => bool **Examples** ```javascript -isNormalized(normal(5, 2)) // returns true +isNormalized(normal(5, 2)); // returns true ``` ### integralSum -Get the sum of the integral of a distribution. If the distribution is normalized, this will be 1. +**Note: If you have suggestions for better names for this, please let us know.** + +Get the sum of the integral of a distribution. If the distribution is normalized, this will be 1.0. This is useful for understanding unnormalized distributions. ``` integralSum: (distribution) => number @@ -444,17 +451,17 @@ integralSum: (distribution) => number **Examples** ```javascript -integralSum(normal(5, 2)) +integralSum(normal(5, 2)); ``` ## Regular Arithmetic Operations Regular arithmetic operations cover the basic mathematical operations on distributions. They work much like their equivalent operations on numbers. -The infixes `+`,`-`, `*`, `/`, `^`, `-` are supported for addition, subtraction, multiplication, division, power, and unaryMinus. +The infixes `+`,`-`, `*`, `/`, `^` are supported for addition, subtraction, multiplication, division, power, and unaryMinus. ```javascript -pointMass(5 + 10) == pointMass(5) + pointMass(10) +pointMass(5 + 10) == pointMass(5) + pointMass(10); ``` ### add @@ -466,13 +473,13 @@ add: (distributionLike, distributionLike) => distribution **Examples** ```javascript -normal(0, 1) + normal(1, 3) // returns normal(1, 3.16...) -add(normal(0, 1), normal(1, 3)) // returns normal(1, 3.16...) +normal(0, 1) + normal(1, 3); // returns normal(1, 3.16...) +add(normal(0, 1), normal(1, 3)); // returns normal(1, 3.16...) ``` ### sum -**Todo: Not yet implemented for distributions** +**Todo: Not yet implemented** ``` sum: (list) => distribution @@ -481,7 +488,7 @@ sum: (list) => distribution **Examples** ```javascript -sum([normal(0, 1), normal(1, 3), uniform(10, 1)]) +sum([normal(0, 1), normal(1, 3), uniform(10, 1)]); ``` ### multiply @@ -541,12 +548,27 @@ unaryMinus: (distribution) => distribution **Examples** ```javascript --normal(5, 2) // same as normal(-5, 2) -unaryMinus(normal(5, 2)) // same as normal(-5, 2) +-normal(5, 2); // same as normal(-5, 2) +unaryMinus(normal(5, 2)); // same as normal(-5, 2) ``` ## Pointwise Arithmetic Operations + +

+ Pointwise arithmetic operations typically return unnormalized or completely + invalid distributions. For example, the operation{" "} + normal(5,2) .- uniform(10,12) results in a distribution-like + object with negative probability mass. +

+
+ +Pointwise arithmetic operations cover the standard arithmetic operations, but work in a different way than the regular operations. These operate on the y-values of the distributions instead of the x-values. A pointwise addition would add the y-values of two distributions. + +The infixes `.+`,`.-`, `.*`, `./`, `.^` are supported for their respective operations. + +The `mixture` methods works with pointwise addition. + ### dotAdd ``` @@ -585,10 +607,20 @@ dotExp: (distributionLike, distributionLike) => distribution ## Scale Arithmetic Operations -### scaleMultiply + +

+ We're planning on removing scale operations in favor of more general + functions soon. +

+
-``` -scaleMultiply: (distributionLike, number) => distribution +Scale operations are similar to pointwise operations, but operate on a constant y-value instead of y-values coming from a distribution. You can think about this as scaling a distribution vertically by a constant. + +The following items would be equivalent. + +```js +scalePow(normal(5,2), 2) +mapY(normal(5,2), {|y| y ^ 2}) // Not yet available ``` ### scalePow @@ -619,7 +651,9 @@ scaleLog10: (distributionLike, number) => distribution ### Declaration (Continuous Functions) -Adds metadata to a function of the input ranges. Works now for numeric and date inputs. This is useful when making predictions. It allows you to limit the domain that your prediction will be used and scored within. +Adds metadata to a function of the input ranges. Works now for numeric and date inputs. This is useful when making formal predictions. It allows you to limit the domain that your prediction will be used and scored within. + +Declarations are currently experimental and will likely be removed or changed in the future. ``` declareFn: (dict<{fn: lambda, inputs: array>}>) => declaration diff --git a/packages/website/docs/Api/Math.md b/packages/website/docs/Api/Math.md index 37f3fe1d..256ab348 100644 --- a/packages/website/docs/Api/Math.md +++ b/packages/website/docs/Api/Math.md @@ -6,7 +6,7 @@ title: Math ### E ``` -Math.E: +Math.e: ``` Euler's number; ≈ 2.718281828459045 @@ -14,7 +14,7 @@ Euler's number; ≈ 2.718281828459045 ### LN2 ``` -Math.LN2: +Math.ln2: ``` Natural logarithm of 2; ≈ 0.6931471805599453 @@ -22,7 +22,7 @@ Natural logarithm of 2; ≈ 0.6931471805599453 ### LN10 ``` -Math.LN10: +Math.ln10: ``` Natural logarithm of 10; ≈ 2.302585092994046 @@ -30,7 +30,7 @@ Natural logarithm of 10; ≈ 2.302585092994046 ### LOG2E ``` -Math.LOG2E: +Math.log2e: ``` Base 2 logarithm of E; ≈ 1.4426950408889634Base 2 logarithm of E; ≈ 1.4426950408889634 @@ -38,7 +38,7 @@ Base 2 logarithm of E; ≈ 1.4426950408889634Base 2 logarithm of E; ≈ 1.442695 ### LOG10E ``` -Math.LOG10E: +Math.log10e: ``` Base 10 logarithm of E; ≈ 0.4342944819032518 @@ -46,7 +46,7 @@ Base 10 logarithm of E; ≈ 0.4342944819032518 ### PI ``` -Math.PI: +Math.pi: ``` Pi - ratio of the circumference to the diameter of a circle; ≈ 3.141592653589793 @@ -54,7 +54,7 @@ Pi - ratio of the circumference to the diameter of a circle; ≈ 3.1415926535897 ### SQRT1_2 ``` -Math.SQRT1_2: +Math.sqrt1_2: ``` Square root of 1/2; ≈ 0.7071067811865476 @@ -62,7 +62,7 @@ Square root of 1/2; ≈ 0.7071067811865476 ### SQRT2 ``` -Math.SQRT2: +Math.sqrt2: ``` Square root of 2; ≈ 1.4142135623730951 @@ -70,7 +70,7 @@ Square root of 2; ≈ 1.4142135623730951 ### PHI ``` -Math.PHI: +Math.phi: ``` Phi is the golden ratio. 1.618033988749895 @@ -78,7 +78,7 @@ Phi is the golden ratio. 1.618033988749895 ### TAU ``` -Math.TAU: +Math.tau: ``` Tau is the ratio constant of a circle's circumference to radius, equal to 2 \* pi. 6.283185307179586 diff --git a/packages/website/docs/Api/Number.mdx b/packages/website/docs/Api/Number.mdx index 6e4015c2..97795462 100644 --- a/packages/website/docs/Api/Number.mdx +++ b/packages/website/docs/Api/Number.mdx @@ -9,57 +9,57 @@ import TOCInline from "@theme/TOCInline"; ### ceil -```javascript -ceil: (number) => number; +``` +ceil: (number) => number ``` ### floor -```javascript -floor: (number) => number; +``` +floor: (number) => number ``` ### abs -```javascript -abs: (number) => number; +``` +abs: (number) => number ``` ### round -```javascript -round: (number) => number; +``` +round: (number) => number ``` ## Statistics ### max -```javascript +``` max: (list) => number ``` ### min -```javascript +``` min: (list) => number ``` ### mean -```javascript +``` mean: (list) => number ``` ### stdev -```javascript +``` stdev: (list) => number ``` ### variance -```javascript +``` variance: (list) => number ``` @@ -67,25 +67,25 @@ variance: (list) => number ### unaryMinus -```javascript -unaryMinus: (number) => number; +``` +unaryMinus: (number) => number ``` ### equal -```javascript -equal: (number, number) => boolean; +``` +equal: (number, number) => boolean ``` ### add -```javascript -add: (number, number) => number; +``` +add: (number, number) => number ``` ### sum -```javascript +``` sum: (list) => number ``` @@ -97,13 +97,13 @@ cumsum: (list) => list ### multiply -```javascript -multiply: (number, number) => number; +``` +multiply: (number, number) => number ``` ### product -```javascript +``` product: (list) => number ``` @@ -115,30 +115,30 @@ cumprod: (list) => list ### subtract -```javascript -subtract: (number, number) => number; +``` +subtract: (number, number) => number ``` ### divide -```javascript -divide: (number, number) => number; +``` +divide: (number, number) => number ``` ### pow -```javascript -pow: (number, number) => number; +``` +pow: (number, number) => number ``` ### exp -```javascript -exp: (number) => number; +``` +exp: (number) => number ``` ### log -```javascript -log: (number) => number; +``` +log: (number) => number ``` From 858e0e5ee58192a1be263765d498978d4757c80b Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Tue, 14 Jun 2022 14:37:59 -0700 Subject: [PATCH 07/19] Small edits to guides section --- packages/website/docs/Guides/DistributionCreation.mdx | 2 +- packages/website/docs/Guides/Functions.mdx | 2 +- packages/website/docs/{Guides => }/Node-Packages.md | 0 packages/website/sidebars.js | 5 +++++ 4 files changed, 7 insertions(+), 2 deletions(-) rename packages/website/docs/{Guides => }/Node-Packages.md (100%) diff --git a/packages/website/docs/Guides/DistributionCreation.mdx b/packages/website/docs/Guides/DistributionCreation.mdx index 3dae8166..5e84b47f 100644 --- a/packages/website/docs/Guides/DistributionCreation.mdx +++ b/packages/website/docs/Guides/DistributionCreation.mdx @@ -1,6 +1,6 @@ --- title: "Distribution Creation" -sidebar_position: 20 +sidebar_position: 2 --- import { SquiggleEditor } from "../../src/components/SquiggleEditor"; diff --git a/packages/website/docs/Guides/Functions.mdx b/packages/website/docs/Guides/Functions.mdx index 4cd32f37..be579834 100644 --- a/packages/website/docs/Guides/Functions.mdx +++ b/packages/website/docs/Guides/Functions.mdx @@ -1,5 +1,5 @@ --- -title: "Functions Reference" +title: "Distribution Functions" sidebar_position: 3 --- diff --git a/packages/website/docs/Guides/Node-Packages.md b/packages/website/docs/Node-Packages.md similarity index 100% rename from packages/website/docs/Guides/Node-Packages.md rename to packages/website/docs/Node-Packages.md diff --git a/packages/website/sidebars.js b/packages/website/sidebars.js index 5c63ccb9..a22b80a8 100644 --- a/packages/website/sidebars.js +++ b/packages/website/sidebars.js @@ -26,6 +26,11 @@ const sidebars = { id: "Introduction", label: "Introduction", }, + { + type: "doc", + id: "Node-Packages", + label: "Node Packages", + }, { type: "category", label: "Guides", From d4e35792115772edcba4a4cf727284cd29058fa1 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Tue, 14 Jun 2022 14:47:09 -0700 Subject: [PATCH 08/19] Fixed link that was breaking build --- packages/website/docs/Guides/Language.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/website/docs/Guides/Language.mdx b/packages/website/docs/Guides/Language.mdx index 31ff041d..4cfd9ea8 100644 --- a/packages/website/docs/Guides/Language.mdx +++ b/packages/website/docs/Guides/Language.mdx @@ -49,6 +49,6 @@ ozzie_estimate(1) * nuno_estimate(1, 1)`} ## See more -- [Distribution creation](./Distributions) +- [Distribution creation](./DistributionCreation) - [Functions reference](./Functions) - [Gallery](../Discussions/Gallery) From 1d4aea27314c9cdf6a29551f6d153aff45873cde Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Tue, 14 Jun 2022 16:12:29 -0700 Subject: [PATCH 09/19] Added descriptions to last API types --- packages/website/docs/Api/DistGeneric.mdx | 4 ++-- packages/website/docs/Api/DistPointSet.md | 7 +++++++ packages/website/docs/Api/DistSampleSet.md | 13 +++++++++++-- packages/website/docs/Api/List.md | 12 +++++++++++- packages/website/docs/Api/Number.mdx | 4 ++++ 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/packages/website/docs/Api/DistGeneric.mdx b/packages/website/docs/Api/DistGeneric.mdx index b3b5025d..a6498dd2 100644 --- a/packages/website/docs/Api/DistGeneric.mdx +++ b/packages/website/docs/Api/DistGeneric.mdx @@ -292,7 +292,7 @@ quantile(normal(5, 2), 0.5); **TODO: Will soon be called "PointSet.make"** -Converts a distribution to the pointSet format +Converts a distribution to the pointSet format. ``` toPointSet: (distribution) => pointSetDistribution @@ -308,7 +308,7 @@ toPointSet(normal(5, 2)); **TODO: Will soon be called "SampleSet.make"** -Converts a distribution to the sampleSet format, with n samples +Converts a distribution to the sampleSet format, with n samples. ``` toSampleSet: (distribution, number) => sampleSetDistribution diff --git a/packages/website/docs/Api/DistPointSet.md b/packages/website/docs/Api/DistPointSet.md index 6fabd158..383d251f 100644 --- a/packages/website/docs/Api/DistPointSet.md +++ b/packages/website/docs/Api/DistPointSet.md @@ -2,6 +2,13 @@ sidebar_position: 4 title: Point Set Distribution --- +:::danger + These functions aren't yet implemented with these specific names. This should be changed soon +::: + +Point set distributions are one of the three distribution formats. They are stored as a list of x-y coordinates representing both discrete and continuous distributions. + +One complication is that it's possible to represent invalid probability distributions in the point set format. For example, you can represent shapes with negative values, or shapes that are not normalized. ### make diff --git a/packages/website/docs/Api/DistSampleSet.md b/packages/website/docs/Api/DistSampleSet.md index 9d0f5ed9..9de3a91f 100644 --- a/packages/website/docs/Api/DistSampleSet.md +++ b/packages/website/docs/Api/DistSampleSet.md @@ -2,13 +2,22 @@ sidebar_position: 5 title: Sample Set Distribution --- +:::danger + These functions aren't yet implemented with these specific names. This should be added soon. +::: + +Sample set distributions are one of the three distribution formats. Internally, they are stored as a list of numbers. It's useful to distinguish point set distributions from arbitrary lists of numbers to make it clear which functions are applicable. + +Monte Carlo calculations typically result in sample set distributions. + +All regular distribution function work on sample set distributions. In addition, there are several functions that only work on sample set distributions. ### make ``` SampleSet.make: (distribution) => sampleSet -SampleSet.make: (() => number) => sampleSet SampleSet.make: (list) => sampleSet +SampleSet.make: (() => number) => sampleSet // not yet implemented ``` ### map @@ -35,7 +44,7 @@ SampleSet.map3: (sampleSet, sampleSet, sampleSet, ((number, number, number) => n SampleSet.toList: (sampleSet) => list ``` -Gets the internal samples of a sampleSet distribution. This is separate from the sampleN() function, which would shuffle the samples. toList() maintains order and length. Gets the internal samples of a sampleSet distribution. This is separate from the sampleN() function, which would shuffle the samples. toList() maintains order and length. +Gets the internal samples of a sampleSet distribution. This is separate from the sampleN() function, which would shuffle the samples. toList() maintains order and length. **Examples** diff --git a/packages/website/docs/Api/List.md b/packages/website/docs/Api/List.md index c6d89e7d..50641a55 100644 --- a/packages/website/docs/Api/List.md +++ b/packages/website/docs/Api/List.md @@ -3,13 +3,21 @@ sidebar_position: 7 title: List --- +Squiggle lists are a lot like Python lists or Ruby arrays. They accept all types. + +```javascript +myList = [3, normal(5,2), "random"] +``` + ### make +**Note: currently just called ``makeList``, without the preix** + ``` List.make: (number, 'a) => list<'a> ``` -Returns an array of size `n` filled with value `e`. +Returns an array of size `n` filled with the value. ```js List.make(4, 1); // creates the list [1, 1, 1, 1] @@ -31,6 +39,8 @@ length: (list<'a>) => number ### up to +**Note: currently just called ``upTo``, without the preix** + ``` List.upTo: (low:number, high:number) => list ``` diff --git a/packages/website/docs/Api/Number.mdx b/packages/website/docs/Api/Number.mdx index 97795462..4e806426 100644 --- a/packages/website/docs/Api/Number.mdx +++ b/packages/website/docs/Api/Number.mdx @@ -3,6 +3,10 @@ sidebar_position: 9 title: Number --- +Squiggle ``numbers`` are Javascript floats. + +Many of the functions below work on lists or pairs of numbers. + import TOCInline from "@theme/TOCInline"; From 605afc03cc75d322753da9bd84de73f9d8915f85 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Tue, 14 Jun 2022 16:47:31 -0700 Subject: [PATCH 10/19] Ran formatter --- packages/website/docs/Api/DistPointSet.md | 3 ++- packages/website/docs/Api/DistSampleSet.md | 7 ++++--- packages/website/docs/Api/List.md | 6 +++--- packages/website/docs/Api/Number.mdx | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/website/docs/Api/DistPointSet.md b/packages/website/docs/Api/DistPointSet.md index 383d251f..b4c4ba81 100644 --- a/packages/website/docs/Api/DistPointSet.md +++ b/packages/website/docs/Api/DistPointSet.md @@ -2,8 +2,9 @@ sidebar_position: 4 title: Point Set Distribution --- + :::danger - These functions aren't yet implemented with these specific names. This should be changed soon +These functions aren't yet implemented with these specific names. This should be changed soon ::: Point set distributions are one of the three distribution formats. They are stored as a list of x-y coordinates representing both discrete and continuous distributions. diff --git a/packages/website/docs/Api/DistSampleSet.md b/packages/website/docs/Api/DistSampleSet.md index 9de3a91f..18005627 100644 --- a/packages/website/docs/Api/DistSampleSet.md +++ b/packages/website/docs/Api/DistSampleSet.md @@ -2,13 +2,14 @@ sidebar_position: 5 title: Sample Set Distribution --- + :::danger - These functions aren't yet implemented with these specific names. This should be added soon. +These functions aren't yet implemented with these specific names. This should be added soon. ::: Sample set distributions are one of the three distribution formats. Internally, they are stored as a list of numbers. It's useful to distinguish point set distributions from arbitrary lists of numbers to make it clear which functions are applicable. -Monte Carlo calculations typically result in sample set distributions. +Monte Carlo calculations typically result in sample set distributions. All regular distribution function work on sample set distributions. In addition, there are several functions that only work on sample set distributions. @@ -44,7 +45,7 @@ SampleSet.map3: (sampleSet, sampleSet, sampleSet, ((number, number, number) => n SampleSet.toList: (sampleSet) => list ``` -Gets the internal samples of a sampleSet distribution. This is separate from the sampleN() function, which would shuffle the samples. toList() maintains order and length. +Gets the internal samples of a sampleSet distribution. This is separate from the sampleN() function, which would shuffle the samples. toList() maintains order and length. **Examples** diff --git a/packages/website/docs/Api/List.md b/packages/website/docs/Api/List.md index 50641a55..47d5f450 100644 --- a/packages/website/docs/Api/List.md +++ b/packages/website/docs/Api/List.md @@ -6,12 +6,12 @@ title: List Squiggle lists are a lot like Python lists or Ruby arrays. They accept all types. ```javascript -myList = [3, normal(5,2), "random"] +myList = [3, normal(5, 2), "random"]; ``` ### make -**Note: currently just called ``makeList``, without the preix** +**Note: currently just called `makeList`, without the preix** ``` List.make: (number, 'a) => list<'a> @@ -39,7 +39,7 @@ length: (list<'a>) => number ### up to -**Note: currently just called ``upTo``, without the preix** +**Note: currently just called `upTo`, without the preix** ``` List.upTo: (low:number, high:number) => list diff --git a/packages/website/docs/Api/Number.mdx b/packages/website/docs/Api/Number.mdx index 4e806426..dda79f64 100644 --- a/packages/website/docs/Api/Number.mdx +++ b/packages/website/docs/Api/Number.mdx @@ -3,7 +3,7 @@ sidebar_position: 9 title: Number --- -Squiggle ``numbers`` are Javascript floats. +Squiggle `numbers` are Javascript floats. Many of the functions below work on lists or pairs of numbers. From 7ceae186119273add26586322342a17df4295c1e Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Tue, 14 Jun 2022 16:54:59 -0700 Subject: [PATCH 11/19] Normalize after trunctae --- .../ReducerInterface/ReducerInterface_Distribution_test.res | 1 + .../squiggle-lang/src/rescript/Distributions/GenericDist.res | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res b/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res index a2fa37df..ecc07bfa 100644 --- a/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res +++ b/packages/squiggle-lang/__tests__/ReducerInterface/ReducerInterface_Distribution_test.res @@ -80,6 +80,7 @@ describe("eval on distribution functions", () => { testEval("truncateLeft(normal(5,2), 3)", "Ok(Point Set Distribution)") testEval("truncateRight(normal(5,2), 3)", "Ok(Point Set Distribution)") testEval("truncate(normal(5,2), 3, 8)", "Ok(Point Set Distribution)") + testEval("isNormalized(truncate(normal(5,2), 3, 8))", "Ok(true)") }) describe("exp", () => { diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res index f7d1e4f5..01532e2a 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res @@ -214,7 +214,7 @@ module Truncate = { | Some(r) => Ok(r) | None => toPointSetFn(t)->E.R2.fmap(t => { - DistributionTypes.PointSet(PointSetDist.T.truncate(leftCutoff, rightCutoff, t)) + DistributionTypes.PointSet(PointSetDist.T.truncate(leftCutoff, rightCutoff, t)->PointSetDist.T.normalize) }) } } From 6278dff81834f7e2e5f6fe1220ba4ccd6ce713a1 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Tue, 14 Jun 2022 17:00:09 -0700 Subject: [PATCH 12/19] Ran formatting --- .../squiggle-lang/src/rescript/Distributions/GenericDist.res | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res index 01532e2a..addbdaa1 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res +++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist.res @@ -214,7 +214,9 @@ module Truncate = { | Some(r) => Ok(r) | None => toPointSetFn(t)->E.R2.fmap(t => { - DistributionTypes.PointSet(PointSetDist.T.truncate(leftCutoff, rightCutoff, t)->PointSetDist.T.normalize) + DistributionTypes.PointSet( + PointSetDist.T.truncate(leftCutoff, rightCutoff, t)->PointSetDist.T.normalize, + ) }) } } From 1a98392c78b6fa9271286a53e3003bef8b3f4225 Mon Sep 17 00:00:00 2001 From: NunoSempere Date: Tue, 14 Jun 2022 23:45:40 -0400 Subject: [PATCH 13/19] fix: Make lodash a dependency, rather than a dev dependency I'm hoping this fixes my current error when using the npm package. Looking at the compiled outputs into js, the first line is: import * as _ from "lodash"; But, because lodash is not a dependency, but rather a dev dependency, this brings up an error when downloading and using from npm, so the current npm package does not run I am hoping that this simple fix will fix that. --- packages/squiggle-lang/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/squiggle-lang/package.json b/packages/squiggle-lang/package.json index abc9f239..417f6bc4 100644 --- a/packages/squiggle-lang/package.json +++ b/packages/squiggle-lang/package.json @@ -38,6 +38,7 @@ "dependencies": { "@stdlib/stats": "^0.0.13", "jstat": "^1.9.5", + "lodash": "^4.17.21", "mathjs": "^10.6.0", "pdfast": "^0.2.0", "rescript": "^9.1.4" @@ -53,7 +54,6 @@ "fast-check": "^2.25.0", "gentype": "^4.4.0", "jest": "^27.5.1", - "lodash": "^4.17.21", "moduleserve": "^0.9.1", "nyc": "^15.1.0", "peggy": "^2.0.1", From ba5f703d03cc227208f89fe2fdf1f4c8aaa84814 Mon Sep 17 00:00:00 2001 From: NunoSempere Date: Wed, 15 Jun 2022 00:15:17 -0400 Subject: [PATCH 14/19] v0.2.11 --- packages/squiggle-lang/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/squiggle-lang/package.json b/packages/squiggle-lang/package.json index 417f6bc4..d3542d62 100644 --- a/packages/squiggle-lang/package.json +++ b/packages/squiggle-lang/package.json @@ -1,6 +1,6 @@ { "name": "@quri/squiggle-lang", - "version": "0.2.9", + "version": "0.2.11", "homepage": "https://squiggle-language.com", "license": "MIT", "scripts": { From e8e8a06f7aaf38c72ac339cfe0726f206d77d7d3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Thu, 16 Jun 2022 13:05:48 +0300 Subject: [PATCH 15/19] useSquiggle and useSquigglePartial hooks --- .../components/src/components/CodeEditor.tsx | 9 +- .../src/components/SquiggleChart.tsx | 285 ++---------------- .../src/components/SquiggleEditor.tsx | 212 +++++-------- .../src/components/SquiggleErrorAlert.tsx | 11 + .../src/components/SquiggleItem.tsx | 250 +++++++++++++++ .../src/components/SquigglePlayground.tsx | 11 +- packages/components/src/index.ts | 2 +- packages/components/src/lib/hooks.ts | 63 ++++ 8 files changed, 438 insertions(+), 405 deletions(-) create mode 100644 packages/components/src/components/SquiggleErrorAlert.tsx create mode 100644 packages/components/src/components/SquiggleItem.tsx create mode 100644 packages/components/src/lib/hooks.ts diff --git a/packages/components/src/components/CodeEditor.tsx b/packages/components/src/components/CodeEditor.tsx index 5d9340b8..c869b2ea 100644 --- a/packages/components/src/components/CodeEditor.tsx +++ b/packages/components/src/components/CodeEditor.tsx @@ -1,5 +1,5 @@ import _ from "lodash"; -import React, { FC } from "react"; +import React, { FC, useMemo } from "react"; import AceEditor from "react-ace"; import "ace-builds/src-noconflict/mode-golang"; @@ -21,14 +21,15 @@ export const CodeEditor: FC = ({ showGutter = false, height, }) => { - let lineCount = value.split("\n").length; - let id = _.uniqueId(); + const lineCount = value.split("\n").length; + const id = useMemo(() => _.uniqueId(), []); + return ( (x: declaration) { - let first = x.args[0]; - switch (first.tag) { - case "Float": { - return { floats: { min: first.value.min, max: first.value.max } }; - } - case "Date": { - return { time: { min: first.value.min, max: first.value.max } }; - } - } -} - -function getChartSettings(x: declaration): FunctionChartSettings { - let range = getRange(x); - let min = range.floats ? range.floats.min : 0; - let max = range.floats ? range.floats.max : 10; - return { - start: min, - stop: max, - count: 20, - }; -} - -interface VariableBoxProps { - heading: string; - children: React.ReactNode; - showTypes: boolean; -} - -export const VariableBox: React.FC = ({ - heading = "Error", - children, - showTypes = false, -}) => { - if (showTypes) { - return ( -
-
-
{heading}
-
-
{children}
-
- ); - } else { - return
{children}
; - } -}; - -export interface SquiggleItemProps { - /** The input string for squiggle */ - expression: squiggleExpression; - width?: number; - height: number; - /** Whether to show a summary of statistics for distributions */ - showSummary: boolean; - /** Whether to show type information */ - showTypes: boolean; - /** Whether to show users graph controls (scale etc) */ - showControls: boolean; - /** Settings for displaying functions */ - chartSettings: FunctionChartSettings; - /** Environment for further function executions */ - environment: environment; -} - -const SquiggleItem: React.FC = ({ - expression, - width, - height, - showSummary, - showTypes = false, - showControls = false, - chartSettings, - environment, -}) => { - switch (expression.tag) { - case "number": - return ( - -
- -
-
- ); - case "distribution": { - let distType = expression.value.type(); - return ( - - {distType === "Symbolic" && showTypes ? ( -
{expression.value.toString()}
- ) : null} - -
- ); - } - case "string": - return ( - - " - - {expression.value} - - " - - ); - case "boolean": - return ( - - {expression.value.toString()} - - ); - case "symbol": - return ( - - Undefined Symbol: - {expression.value} - - ); - case "call": - return ( - - {expression.value} - - ); - case "array": - return ( - - {expression.value.map((r, i) => ( -
-
-
{i}
-
-
- -
-
- ))} -
- ); - case "record": - return ( - -
- {Object.entries(expression.value).map(([key, r]) => ( -
-
-
{key}:
-
-
- -
-
- ))} -
-
- ); - case "arraystring": - return ( - - {expression.value.map((r) => `"${r}"`).join(", ")} - - ); - case "date": - return ( - - {expression.value.toDateString()} - - ); - case "timeDuration": { - return ( - - - - ); - } - case "lambda": - return ( - -
{`function(${expression.value.parameters.join( - "," - )})`}
- -
- ); - case "lambdaDeclaration": { - return ( - - - - ); - } - default: { - return <>Should be unreachable; - } - } -}; +import { FunctionChartSettings } from "./FunctionChart"; +import { useSquiggle } from "../lib/hooks"; +import { SquiggleErrorAlert } from "./SquiggleErrorAlert"; +import { SquiggleItem } from "./SquiggleItem"; export interface SquiggleChartProps { /** The input string for squiggle */ @@ -266,8 +22,8 @@ export interface SquiggleChartProps { environment?: environment; /** If the result is a function, where the function starts, ends and the amount of stops */ chartSettings?: FunctionChartSettings; - /** When the environment changes */ - onChange?(expr: squiggleExpression): void; + /** When the squiggle code gets reevaluated */ + onChange?(expr: squiggleExpression | undefined): void; /** CSS width of the element */ width?: number; height?: number; @@ -275,7 +31,7 @@ export interface SquiggleChartProps { bindings?: bindings; /** JS imported parameters */ jsImports?: jsImports; - /** Whether to show a summary of the distirbution */ + /** Whether to show a summary of the distribution */ showSummary?: boolean; /** Whether to show type information about returns, default false */ showTypes?: boolean; @@ -283,12 +39,13 @@ export interface SquiggleChartProps { showControls?: boolean; } +const defaultOnChange = () => {}; const defaultChartSettings = { start: 0, stop: 10, count: 20 }; export const SquiggleChart: React.FC = ({ squiggleString = "", environment, - onChange = () => {}, + onChange = defaultOnChange, // defaultOnChange must be constant, don't move its definition here height = 200, bindings = defaultBindings, jsImports = defaultImports, @@ -298,28 +55,28 @@ export const SquiggleChart: React.FC = ({ showControls = false, chartSettings = defaultChartSettings, }) => { - let expressionResult = run(squiggleString, bindings, environment, jsImports); - if (expressionResult.tag !== "Ok") { - return ( - - {errorValueToString(expressionResult.value)} - - ); + const { result } = useSquiggle({ + code: squiggleString, + bindings, + environment, + jsImports, + onChange, + }); + + if (result.tag !== "Ok") { + return ; } - let e = environment ?? defaultEnvironment; - let expression = expressionResult.value; - onChange(expression); return ( ); }; diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx index a8db78af..279d6ec6 100644 --- a/packages/components/src/components/SquiggleEditor.tsx +++ b/packages/components/src/components/SquiggleEditor.tsx @@ -1,39 +1,51 @@ -import * as React from "react"; +import React, { useState } from "react"; import * as ReactDOM from "react-dom"; -import { SquiggleChart } from "./SquiggleChart"; import { CodeEditor } from "./CodeEditor"; -import type { +import { squiggleExpression, environment, bindings, jsImports, + defaultEnvironment, } from "@quri/squiggle-lang"; -import { - runPartial, - errorValueToString, - defaultImports, - defaultBindings, -} from "@quri/squiggle-lang"; -import { ErrorAlert } from "./Alert"; +import { defaultImports, defaultBindings } from "@quri/squiggle-lang"; import { SquiggleContainer } from "./SquiggleContainer"; +import { useSquiggle, useSquigglePartial } from "../lib/hooks"; +import { SquiggleErrorAlert } from "./SquiggleErrorAlert"; +import { SquiggleItem } from "./SquiggleItem"; + +const WrappedCodeEditor: React.FC<{ + code: string; + setCode: (code: string) => void; +}> = ({ code, setCode }) => ( +
+ +
+); export interface SquiggleEditorProps { /** The input string for squiggle */ initialSquiggleString?: string; - /** If the output requires monte carlo sampling, the amount of samples */ - environment?: environment; + /** The width of the element */ + width?: number; /** If the result is a function, where the function starts */ diagramStart?: number; /** If the result is a function, where the function ends */ diagramStop?: number; /** If the result is a function, how many points along the function it samples */ diagramCount?: number; - /** when the environment changes. Used again for notebook magic*/ - onChange?(expr: squiggleExpression): void; - /** The width of the element */ - width?: number; + /** When the environment changes. Used again for notebook magic */ + onChange?(expr: squiggleExpression | undefined): void; /** Previous variable declarations */ bindings?: bindings; + /** If the output requires monte carlo sampling, the amount of samples */ + environment?: environment; /** JS Imports */ jsImports?: jsImports; /** Whether to show detail about types of the returns, default false */ @@ -44,169 +56,109 @@ export interface SquiggleEditorProps { showSummary?: boolean; } -export let SquiggleEditor: React.FC = ({ +export const SquiggleEditor: React.FC = ({ initialSquiggleString = "", width, - environment, diagramStart = 0, diagramStop = 10, diagramCount = 20, onChange, bindings = defaultBindings, + environment, jsImports = defaultImports, showTypes = false, showControls = false, showSummary = false, }: SquiggleEditorProps) => { - const [expression, setExpression] = React.useState(initialSquiggleString); + const [code, setCode] = useState(initialSquiggleString); + + const { result, observableRef } = useSquiggle({ + code, + bindings, + environment, + jsImports, + onChange, + }); + const chartSettings = { start: diagramStart, stop: diagramStop, count: diagramCount, }; + return ( - -
-
- + + + {result.tag === "Ok" ? ( + -
- -
-
+ ) : ( + + )} + + ); }; export function renderSquiggleEditorToDom(props: SquiggleEditorProps) { - let parent = document.createElement("div"); - ReactDOM.render( - { - // Typescript complains on two levels here. - // - Div elements don't have a value property - // - Even if it did (like it was an input element), it would have to - // be a string - // - // Which are reasonable in most web contexts. - // - // However we're using observable, neither of those things have to be - // true there. div elements can contain the value property, and can have - // the value be any datatype they wish. - // - // This is here to get the 'viewof' part of: - // viewof env = cell('normal(0,1)') - // to work - // @ts-ignore - parent.value = expr; - - parent.dispatchEvent(new CustomEvent("input")); - if (props.onChange) props.onChange(expr); - }} - />, - parent - ); + const parent = document.createElement("div"); + ReactDOM.render(, parent); return parent; } export interface SquigglePartialProps { /** The input string for squiggle */ initialSquiggleString?: string; - /** If the output requires monte carlo sampling, the amount of samples */ - environment?: environment; - /** If the result is a function, where the function starts */ - diagramStart?: number; - /** If the result is a function, where the function ends */ - diagramStop?: number; - /** If the result is a function, how many points along the function it samples */ - diagramCount?: number; /** when the environment changes. Used again for notebook magic*/ - onChange?(expr: bindings): void; + onChange?(expr: bindings | undefined): void; /** Previously declared variables */ bindings?: bindings; + /** If the output requires monte carlo sampling, the amount of samples */ + environment?: environment; /** Variables imported from js */ jsImports?: jsImports; - /** Whether to give users access to graph controls */ - showControls?: boolean; } -export let SquigglePartial: React.FC = ({ +export const SquigglePartial: React.FC = ({ initialSquiggleString = "", onChange, bindings = defaultBindings, environment, jsImports = defaultImports, }: SquigglePartialProps) => { - const [expression, setExpression] = React.useState(initialSquiggleString); - const [error, setError] = React.useState(null); + const [code, setCode] = useState(initialSquiggleString); - const runSquiggleAndUpdateBindings = () => { - const squiggleResult = runPartial( - expression, - bindings, - environment, - jsImports - ); - if (squiggleResult.tag === "Ok") { - if (onChange) onChange(squiggleResult.value); - setError(null); - } else { - setError(errorValueToString(squiggleResult.value)); - } - }; - - React.useEffect(runSquiggleAndUpdateBindings, [expression]); + const { result, observableRef } = useSquigglePartial({ + code, + bindings, + environment, + jsImports, + onChange, + }); return ( - -
-
- -
- {error !== null ? ( - {error} +
+ + + {result.tag !== "Ok" ? ( + ) : null} -
- + +
); }; export function renderSquigglePartialToDom(props: SquigglePartialProps) { - let parent = document.createElement("div"); - ReactDOM.render( - { - // @ts-ignore - parent.value = bindings; - - parent.dispatchEvent(new CustomEvent("input")); - if (props.onChange) props.onChange(bindings); - }} - />, - parent - ); + const parent = document.createElement("div"); + ReactDOM.render(, parent); return parent; } diff --git a/packages/components/src/components/SquiggleErrorAlert.tsx b/packages/components/src/components/SquiggleErrorAlert.tsx new file mode 100644 index 00000000..31d7e352 --- /dev/null +++ b/packages/components/src/components/SquiggleErrorAlert.tsx @@ -0,0 +1,11 @@ +import { errorValue, errorValueToString } from "@quri/squiggle-lang"; +import React from "react"; +import { ErrorAlert } from "./Alert"; + +type Props = { + error: errorValue; +}; + +export const SquiggleErrorAlert: React.FC = ({ error }) => { + return {errorValueToString(error)}; +}; diff --git a/packages/components/src/components/SquiggleItem.tsx b/packages/components/src/components/SquiggleItem.tsx new file mode 100644 index 00000000..0e775f33 --- /dev/null +++ b/packages/components/src/components/SquiggleItem.tsx @@ -0,0 +1,250 @@ +import * as React from "react"; +import { + squiggleExpression, + environment, + declaration, +} from "@quri/squiggle-lang"; +import { NumberShower } from "./NumberShower"; +import { DistributionChart } from "./DistributionChart"; +import { FunctionChart, FunctionChartSettings } from "./FunctionChart"; + +function getRange
(x: declaration) { + const first = x.args[0]; + switch (first.tag) { + case "Float": { + return { floats: { min: first.value.min, max: first.value.max } }; + } + case "Date": { + return { time: { min: first.value.min, max: first.value.max } }; + } + } +} + +function getChartSettings(x: declaration): FunctionChartSettings { + const range = getRange(x); + const min = range.floats ? range.floats.min : 0; + const max = range.floats ? range.floats.max : 10; + return { + start: min, + stop: max, + count: 20, + }; +} + +interface VariableBoxProps { + heading: string; + children: React.ReactNode; + showTypes: boolean; +} + +export const VariableBox: React.FC = ({ + heading = "Error", + children, + showTypes = false, +}) => { + if (showTypes) { + return ( +
+
+
{heading}
+
+
{children}
+
+ ); + } else { + return
{children}
; + } +}; + +export interface SquiggleItemProps { + /** The input string for squiggle */ + expression: squiggleExpression; + width?: number; + height: number; + /** Whether to show a summary of statistics for distributions */ + showSummary: boolean; + /** Whether to show type information */ + showTypes: boolean; + /** Whether to show users graph controls (scale etc) */ + showControls: boolean; + /** Settings for displaying functions */ + chartSettings: FunctionChartSettings; + /** Environment for further function executions */ + environment: environment; +} + +export const SquiggleItem: React.FC = ({ + expression, + width, + height, + showSummary, + showTypes = false, + showControls = false, + chartSettings, + environment, +}) => { + switch (expression.tag) { + case "number": + return ( + +
+ +
+
+ ); + case "distribution": { + const distType = expression.value.type(); + return ( + + {distType === "Symbolic" && showTypes ? ( +
{expression.value.toString()}
+ ) : null} + +
+ ); + } + case "string": + return ( + + " + + {expression.value} + + " + + ); + case "boolean": + return ( + + {expression.value.toString()} + + ); + case "symbol": + return ( + + Undefined Symbol: + {expression.value} + + ); + case "call": + return ( + + {expression.value} + + ); + case "array": + return ( + + {expression.value.map((r, i) => ( +
+
+
{i}
+
+
+ +
+
+ ))} +
+ ); + case "record": + return ( + +
+ {Object.entries(expression.value).map(([key, r]) => ( +
+
+
{key}:
+
+
+ +
+
+ ))} +
+
+ ); + case "arraystring": + return ( + + {expression.value.map((r) => `"${r}"`).join(", ")} + + ); + case "date": + return ( + + {expression.value.toDateString()} + + ); + case "timeDuration": { + return ( + + + + ); + } + case "lambda": + return ( + +
{`function(${expression.value.parameters.join( + "," + )})`}
+ +
+ ); + case "lambdaDeclaration": { + return ( + + + + ); + } + default: { + return <>Should be unreachable; + } + } +}; diff --git a/packages/components/src/components/SquigglePlayground.tsx b/packages/components/src/components/SquigglePlayground.tsx index a0615ca4..64b56358 100644 --- a/packages/components/src/components/SquigglePlayground.tsx +++ b/packages/components/src/components/SquigglePlayground.tsx @@ -190,7 +190,7 @@ function Checkbox({ ); } -const SquigglePlayground: FC = ({ +export const SquigglePlayground: FC = ({ initialSquiggleString = "", height = 500, showTypes = false, @@ -207,9 +207,9 @@ const SquigglePlayground: FC = ({ sampleCount: 1000, xyPointLength: 1000, chartHeight: 150, - showTypes: showTypes, - showControls: showControls, - showSummary: showSummary, + showTypes, + showControls, + showSummary, leftSizePercent: 50, showSettingsPage: false, diagramStart: 0, @@ -414,9 +414,9 @@ const SquigglePlayground: FC = ({ height={vars.chartHeight} showTypes={vars.showTypes} showControls={vars.showControls} + showSummary={vars.showSummary} bindings={defaultBindings} jsImports={imports} - showSummary={vars.showSummary} /> @@ -426,7 +426,6 @@ const SquigglePlayground: FC = ({ ); }; -export default SquigglePlayground; export function renderSquigglePlaygroundToDom(props: PlaygroundProps) { const parent = document.createElement("div"); ReactDOM.render(, parent); diff --git a/packages/components/src/index.ts b/packages/components/src/index.ts index 7a7751a2..de0b6dff 100644 --- a/packages/components/src/index.ts +++ b/packages/components/src/index.ts @@ -6,7 +6,7 @@ export { renderSquigglePartialToDom, } from "./components/SquiggleEditor"; export { - default as SquigglePlayground, + SquigglePlayground, renderSquigglePlaygroundToDom, } from "./components/SquigglePlayground"; export { SquiggleContainer } from "./components/SquiggleContainer"; diff --git a/packages/components/src/lib/hooks.ts b/packages/components/src/lib/hooks.ts new file mode 100644 index 00000000..42db01ce --- /dev/null +++ b/packages/components/src/lib/hooks.ts @@ -0,0 +1,63 @@ +import { + bindings, + environment, + jsImports, + run, + runPartial, +} from "@quri/squiggle-lang"; +import { useEffect, useMemo, useRef } from "react"; + +type SquiggleArgs> = { + code: string; + bindings?: bindings; + jsImports?: jsImports; + environment?: environment; + onChange?: (expr: Extract["value"] | undefined) => void; +}; + +const useSquiggleAny = >( + args: SquiggleArgs, + f: (...args: Parameters) => T +) => { + // We're using observable, where div elements can have a `value` property: + // https://observablehq.com/@observablehq/introduction-to-views + // + // This is here to get the 'viewof' part of: + // viewof env = cell('normal(0,1)') + // to work + const ref = useRef< + HTMLDivElement & { value?: Extract["value"] } + >(null); + const result: T = useMemo( + () => f(args.code, args.bindings, args.environment, args.jsImports), + [f, args.code, args.bindings, args.environment, args.jsImports] + ); + + useEffect(() => { + if (!ref.current) return; + ref.current.value = result.tag === "Ok" ? result.value : undefined; + + ref.current.dispatchEvent(new CustomEvent("input")); + }, [result]); + + const { onChange } = args; + + useEffect(() => { + onChange?.(result.tag === "Ok" ? result.value : undefined); + }, [result, onChange]); + + return { + result, // squiggleExpression or externalBindings + observableRef: ref, // can be passed to outermost
if you want to use your component as an observablehq's view + }; +}; + +export const useSquigglePartial = ( + args: SquiggleArgs> +) => { + return useSquiggleAny(args, runPartial); +}; + +export const useSquiggle = (args: SquiggleArgs>) => { + return useSquiggleAny(args, run); +}; From 8d311a099d8161988f868c05467aa532862b6be2 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 17 Jun 2022 06:44:06 -0700 Subject: [PATCH 16/19] Added scaleMultiply --- .../src/rescript/Distributions/DistributionOperation.res | 6 ++++++ .../src/rescript/Distributions/DistributionOperation.resi | 2 ++ .../src/rescript/Distributions/DistributionTypes.res | 3 +++ .../ReducerInterface_GenericDistribution.res | 2 ++ 4 files changed, 13 insertions(+) diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.res index 668fcd07..25eb70f2 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.res @@ -182,6 +182,11 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => { ) ->E.R2.fmap(r => Dist(r)) ->OutputLocal.fromResult + | ToDist(Scale(#Multiply, f)) => + dist + ->GenericDist.pointwiseCombinationFloat(~toPointSetFn, ~algebraicCombination=#Multiply, ~f) + ->E.R2.fmap(r => Dist(r)) + ->OutputLocal.fromResult | ToDist(Scale(#Logarithm, f)) => dist ->GenericDist.pointwiseCombinationFloat(~toPointSetFn, ~algebraicCombination=#Logarithm, ~f) @@ -298,6 +303,7 @@ module Constructors = { let algebraicLogarithm = (~env, dist1, dist2) => C.algebraicLogarithm(dist1, dist2)->run(~env)->toDistR let algebraicPower = (~env, dist1, dist2) => C.algebraicPower(dist1, dist2)->run(~env)->toDistR + let scaleMultiply = (~env, dist, n) => C.scaleMultiply(dist, n)->run(~env)->toDistR let scalePower = (~env, dist, n) => C.scalePower(dist, n)->run(~env)->toDistR let scaleLogarithm = (~env, dist, n) => C.scaleLogarithm(dist, n)->run(~env)->toDistR let pointwiseAdd = (~env, dist1, dist2) => C.pointwiseAdd(dist1, dist2)->run(~env)->toDistR diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.resi b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.resi index 454b2729..bfa7b3ad 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.resi +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation.resi @@ -102,6 +102,8 @@ module Constructors: { @genType let scaleLogarithm: (~env: env, genericDist, float) => result @genType + let scaleMultiply: (~env: env, genericDist, float) => result + @genType let scalePower: (~env: env, genericDist, float) => result @genType let pointwiseAdd: (~env: env, genericDist, genericDist) => result diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res index cdb0ee3d..a23c2cd6 100644 --- a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res +++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res @@ -76,6 +76,7 @@ module DistributionOperation = { ] type toScaleFn = [ + | #Multiply | #Power | #Logarithm | #LogarithmWithThreshold(float) @@ -138,6 +139,7 @@ module DistributionOperation = { | ToDist(Truncate(_, _)) => `truncate` | ToDist(Inspect) => `inspect` | ToDist(Scale(#Power, r)) => `scalePower(${E.Float.toFixed(r)})` + | ToDist(Scale(#Multiply, r)) => `scaleMultiply(${E.Float.toFixed(r)})` | ToDist(Scale(#Logarithm, r)) => `scaleLog(${E.Float.toFixed(r)})` | ToDist(Scale(#LogarithmWithThreshold(eps), r)) => `scaleLogWithThreshold(${E.Float.toFixed(r)}, epsilon=${E.Float.toFixed(eps)})` @@ -179,6 +181,7 @@ module Constructors = { ToScore(LogScore(answer, prior)), prediction, ) + let scaleMultiply = (dist, n): t => FromDist(ToDist(Scale(#Multiply, n)), dist) let scalePower = (dist, n): t => FromDist(ToDist(Scale(#Power, n)), dist) let scaleLogarithm = (dist, n): t => FromDist(ToDist(Scale(#Logarithm, n)), dist) let scaleLogarithmWithThreshold = (dist, n, eps): t => FromDist( diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res index c0418df8..762f4125 100644 --- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res +++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res @@ -266,6 +266,8 @@ let dispatchToGenericOutput = ( Helpers.toDistFn(Scale(#Logarithm, float), dist, ~env) | ("scaleLogWithThreshold", [EvDistribution(dist), EvNumber(base), EvNumber(eps)]) => Helpers.toDistFn(Scale(#LogarithmWithThreshold(eps), base), dist, ~env) + | ("scaleMultiply", [EvDistribution(dist), EvNumber(float)]) => + Helpers.toDistFn(Scale(#Multiply, float), dist, ~env) | ("scalePow", [EvDistribution(dist), EvNumber(float)]) => Helpers.toDistFn(Scale(#Power, float), dist, ~env) | ("scaleExp", [EvDistribution(dist)]) => From 86fa502e5a5268836566d0aa263dafcd5d911e54 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 17 Jun 2022 06:49:55 -0700 Subject: [PATCH 17/19] Added scaleMultiply to docs --- packages/website/docs/Api/DistGeneric.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/website/docs/Api/DistGeneric.mdx b/packages/website/docs/Api/DistGeneric.mdx index a6498dd2..84e45eaf 100644 --- a/packages/website/docs/Api/DistGeneric.mdx +++ b/packages/website/docs/Api/DistGeneric.mdx @@ -623,6 +623,12 @@ scalePow(normal(5,2), 2) mapY(normal(5,2), {|y| y ^ 2}) // Not yet available ``` +### scaleMultiply + +``` +scaleMultiply: (distributionLike, number) => distribution +``` + ### scalePow ``` From 8f3502b1a20b074337aad1c25bfcee07727f2930 Mon Sep 17 00:00:00 2001 From: Ozzie Gooen Date: Fri, 17 Jun 2022 07:47:46 -0700 Subject: [PATCH 18/19] Ran formatter --- packages/website/docs/Api/DistGeneric.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/website/docs/Api/DistGeneric.mdx b/packages/website/docs/Api/DistGeneric.mdx index 84e45eaf..e49eec1c 100644 --- a/packages/website/docs/Api/DistGeneric.mdx +++ b/packages/website/docs/Api/DistGeneric.mdx @@ -623,7 +623,7 @@ scalePow(normal(5,2), 2) mapY(normal(5,2), {|y| y ^ 2}) // Not yet available ``` -### scaleMultiply +### scaleMultiply ``` scaleMultiply: (distributionLike, number) => distribution From 588cf0cb2771824ca10bef85e88ef5655be89797 Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Fri, 17 Jun 2022 22:25:36 +0300 Subject: [PATCH 19/19] fix SquigglePlayground in storybook --- packages/components/src/stories/SquigglePlayground.stories.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/src/stories/SquigglePlayground.stories.mdx b/packages/components/src/stories/SquigglePlayground.stories.mdx index 5e869633..eb39bbba 100644 --- a/packages/components/src/stories/SquigglePlayground.stories.mdx +++ b/packages/components/src/stories/SquigglePlayground.stories.mdx @@ -1,4 +1,4 @@ -import SquigglePlayground from "../components/SquigglePlayground"; +import { SquigglePlayground } from "../components/SquigglePlayground"; import { Canvas, Meta, Story, Props } from "@storybook/addon-docs";