From b0cf8adb9f38bf0d22bcf4400b08723eb47d6c3f Mon Sep 17 00:00:00 2001 From: Quinn Dougherty Date: Wed, 13 Apr 2022 14:46:01 -0400 Subject: [PATCH] migrated `invariants.md` to `docusaurus` --- packages/website/docs/Internal/Invariants.md | 123 +++++++++++++++++++ packages/website/docusaurus.config.js | 19 ++- packages/website/package.json | 5 +- packages/website/sidebars.js | 10 ++ yarn.lock | 74 ++++++++++- 5 files changed, 225 insertions(+), 6 deletions(-) create mode 100644 packages/website/docs/Internal/Invariants.md diff --git a/packages/website/docs/Internal/Invariants.md b/packages/website/docs/Internal/Invariants.md new file mode 100644 index 00000000..ca302a2c --- /dev/null +++ b/packages/website/docs/Internal/Invariants.md @@ -0,0 +1,123 @@ +--- +title: Statistical properties of algebraic combinations of distributions for property testing. +urlcolor: blue +author: + - Nuño Sempere + - Quinn Dougherty +abstract: This document outlines some properties about algebraic combinations of distributions. It is meant to facilitate property tests for [Squiggle](https://squiggle-language.com/), an estimation language for forecasters. So far, we are focusing on the means, the standard deviation and the shape of the pdfs. +--- + +The academic keyword to search for in relation to this document is "[algebra of random variables](https://wikiless.org/wiki/Algebra_of_random_variables?lang=en)". Squiggle doesn't yet support getting the standard deviation, denoted by $\sigma$, but such support could yet be added. + +## Means and standard deviations + +### Sums + +$$ +mean(f+g) = mean(f) + mean(g) +$$ + +$$\sigma(f+g) = \sqrt{\sigma(f)^2 + \sigma(g)^2} +$$ + +In the case of normal distributions, + +$$ +mean(normal(a,b) + normal(c,d)) = mean(normal(a+c, \sqrt{b^2 + d^2})) +$$ + +### Subtractions + +$$ +mean(f-g) = mean(f) - mean(g) +$$ + +$$ +\sigma(f-g) = \sqrt{\sigma(f)^2 + \sigma(g)^2} +$$ + +### Multiplications + +$$ +mean(f \cdot g) = mean(f) \cdot mean(g) +$$ + +$$ +\sigma(f \cdot g) = \sqrt{ (\sigma(f)^2 + mean(f)) \cdot (\sigma(g)^2 + mean(g)) - (mean(f) \cdot mean(g))^2} +$$ + +### Divisions + +Divisions are tricky, and in general we don't have good expressions to characterize properties of ratios. In particular, the ratio of two normals is a Cauchy distribution, which doesn't have to have a mean. + +## Probability density functions (pdfs) + +Specifying the pdf of the sum/multiplication/... of distributions as a function of the pdfs of the individual arguments can still be done. But it requires integration. My sense is that this is still doable, and I (Nuño) provide some _pseudocode_ to do this. + +### Sums + +Let $f, g$ be two independently distributed functions. Then, the pdf of their sum, evaluated at a point $z$, expressed as $(f + g)(z)$, is given by: + +$$ +(f + g)(z)= \int_{-\infty}^{\infty} f(x)\cdot g(z-x) \,dx +$$ + +See a proof sketch [here](https://www.milefoot.com/math/stat/rv-sums.htm) + +Here is some pseudocode to approximate this: + +```js +// pdf1 and pdf2 are pdfs, +// and cdf1 and cdf2 are their corresponding cdfs + +let epsilonForBounds = 2 ** -16; +let getBounds = (cdf) => { + let cdf_min = -1; + let cdf_max = 1; + let n = 0; + while ( + (cdf(cdf_min) > epsilonForBounds || 1 - cdf(cdf_max) > epsilonForBounds) && + n < 10 + ) { + if (cdf(cdf_min) > epsilonForBounds) { + cdf_min = cdf_min * 2; + } + if (1 - cdf(cdf_max) > epsilonForBounds) { + cdf_max = cdf_max * 2; + } + } + return [cdf_min, cdf_max]; +}; + +let epsilonForIntegrals = 2 ** -16; +let pdfOfSum = (pdf1, pdf2, cdf1, cdf2, z) => { + let bounds1 = getBounds(cdf1); + let bounds2 = getBounds(cdf2); + let bounds = [ + Math.min(bounds1[0], bounds2[0]), + Math.max(bounds1[1], bounds2[1]), + ]; + + let result = 0; + for (let x = bounds[0]; (x = x + epsilonForIntegrals); x < bounds[1]) { + let delta = pdf1(x) * pdf2(z - x); + result = result + delta * epsilonForIntegrals; + } + return result; +}; +``` + +## Cumulative density functions + +TODO + +## Inverse cumulative density functions + +TODO + +# To do: + +- Provide sources or derivations, useful as this document becomes more complicated +- Provide definitions for the probability density function, exponential, inverse, log, etc. +- Provide at least some tests for division +- See if playing around with characteristic functions turns out anything useful diff --git a/packages/website/docusaurus.config.js b/packages/website/docusaurus.config.js index 0b3d2d04..c5d03327 100644 --- a/packages/website/docusaurus.config.js +++ b/packages/website/docusaurus.config.js @@ -1,5 +1,7 @@ // @ts-check // Note: type annotations allow type checking and IDEs autocompletion +const math = require("remark-math"); +const katex = require("rehype-katex"); const lightCodeTheme = require("prism-react-renderer/themes/github"); const darkCodeTheme = require("prism-react-renderer/themes/dracula"); @@ -14,7 +16,7 @@ const config = { onBrokenLinks: "throw", onBrokenMarkdownLinks: "warn", favicon: "img/favicon.ico", - organizationName: "QURIResearch", // Usually your GitHub org/user name. + organizationName: "quantified-uncertainty", // Usually your GitHub org/user name. projectName: "squiggle", // Usually your repo name. plugins: [ @@ -47,13 +49,15 @@ const config = { sidebarPath: require.resolve("./sidebars.js"), // Please change this to your repo. editUrl: - "https://github.com/foretold-app/squiggle/tree/master/packages/website/", + "https://github.com/quantified-uncertainty/squiggle/tree/master/packages/website/", + remarkPlugins: [math], + rehypePlugins: [katex], }, blog: { showReadingTime: true, // Please change this to your repo. editUrl: - "https://github.com/foretold-app/squiggle/tree/master/packages/website/", + "https://github.com/quantified-uncertainty/squiggle/tree/master/packages/website/", }, theme: { customCss: require.resolve("./src/css/custom.css"), @@ -111,6 +115,15 @@ const config = { darkTheme: darkCodeTheme, }, }), + stylesheets: [ + { + href: "https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css", + type: "text/css", + integrity: + "sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM", + crossorigin: "anonymous", + }, + ], }; module.exports = config; diff --git a/packages/website/package.json b/packages/website/package.json index e0b0132b..d8e9c83d 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -17,7 +17,10 @@ "clsx": "^1.1.1", "prism-react-renderer": "^1.2.1", "react": "^18.0.0", - "react-dom": "^18.0.0" + "react-dom": "^18.0.0", + "remark-math": "^3", + "rehype-katex": "^5", + "hast-util-is-element": "1.1.0" }, "browserslist": { "production": [ diff --git a/packages/website/sidebars.js b/packages/website/sidebars.js index 4685c349..78ad249f 100644 --- a/packages/website/sidebars.js +++ b/packages/website/sidebars.js @@ -40,6 +40,16 @@ const sidebars = { }, ], }, + { + type: "category", + label: "Internal", + items: [ + { + type: "autogenerated", + dirName: "Internal", + }, + ], + }, ], // But you can create a sidebar manually diff --git a/yarn.lock b/yarn.lock index 056754e3..467d77ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3890,6 +3890,11 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= +"@types/katex@^0.11.0": + version "0.11.1" + resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.11.1.tgz#34de04477dcf79e2ef6c8d23b41a3d81f9ebeaf5" + integrity sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg== + "@types/lodash@^4.14.181": version "4.14.181" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.181.tgz#d1d3740c379fda17ab175165ba04e2d03389385d" @@ -6394,7 +6399,7 @@ commander@^6.2.1: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== -commander@^8.3.0: +commander@^8.0.0, commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== @@ -9278,6 +9283,11 @@ hast-util-from-parse5@^6.0.0: vfile-location "^3.2.0" web-namespaces "^1.0.0" +hast-util-is-element@1.1.0, hast-util-is-element@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425" + integrity sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ== + hast-util-parse-selector@^2.0.0: version "2.2.5" resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" @@ -9310,6 +9320,15 @@ hast-util-to-parse5@^6.0.0: xtend "^4.0.0" zwitch "^1.0.0" +hast-util-to-text@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-2.0.1.tgz#04f2e065642a0edb08341976084aa217624a0f8b" + integrity sha512-8nsgCARfs6VkwH2jJU9b8LNTuR4700na+0h3PqCaEk4MAnMDeu5P0tP8mjk9LLNGxIeQRLbiDbZVw6rku+pYsQ== + dependencies: + hast-util-is-element "^1.0.0" + repeat-string "^1.0.0" + unist-util-find-after "^3.0.0" + hastscript@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" @@ -10968,6 +10987,13 @@ junk@^3.1.0: resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== +katex@^0.13.0: + version "0.13.24" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.24.tgz#fe55455eb455698cb24b911a353d16a3c855d905" + integrity sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w== + dependencies: + commander "^8.0.0" + keyv@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" @@ -14541,6 +14567,18 @@ regjsparser@^0.8.2: dependencies: jsesc "~0.5.0" +rehype-katex@^5: + version "5.0.0" + resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-5.0.0.tgz#b556f24fde918f28ba1cb642ea71c7e82f3373d7" + integrity sha512-ksSuEKCql/IiIadOHiKRMjypva9BLhuwQNascMqaoGLDVd0k2NlE2wMvgZ3rpItzRKCd6vs8s7MFbb8pcR0AEg== + dependencies: + "@types/katex" "^0.11.0" + hast-util-to-text "^2.0.0" + katex "^0.13.0" + rehype-parse "^7.0.0" + unified "^9.0.0" + unist-util-visit "^2.0.0" + rehype-parse@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964" @@ -14550,6 +14588,14 @@ rehype-parse@^6.0.2: parse5 "^5.0.0" xtend "^4.0.0" +rehype-parse@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57" + integrity sha512-fOiR9a9xH+Le19i4fGzIEowAbwG7idy2Jzs4mOrFWBSJ0sNUgy0ev871dwWnbOo371SjgjG4pwzrbgSVrKxecw== + dependencies: + hast-util-from-parse5 "^6.0.0" + parse5 "^6.0.0" + relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" @@ -14589,6 +14635,11 @@ remark-footnotes@2.0.0: resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ== +remark-math@^3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/remark-math/-/remark-math-3.0.1.tgz#85a02a15b15cad34b89a27244d4887b3a95185bb" + integrity sha512-epT77R/HK0x7NqrWHdSV75uNLwn8g9qTyMqCRCDujL0vj/6T6+yhdrR7mjELWtkse+Fw02kijAaBuVcHBor1+Q== + remark-mdx@1.6.22: version "1.6.22" resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" @@ -14673,7 +14724,7 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.0.0, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= @@ -16509,6 +16560,18 @@ unified@^8.4.2: trough "^1.0.0" vfile "^4.0.0" +unified@^9.0.0: + version "9.2.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" + integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -16545,6 +16608,13 @@ unist-builder@2.0.3, unist-builder@^2.0.0: resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== +unist-util-find-after@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-3.0.0.tgz#5c65fcebf64d4f8f496db46fa8fd0fbf354b43e6" + integrity sha512-ojlBqfsBftYXExNu3+hHLfJQ/X1jYY/9vdm4yZWjIbf0VuWF6CRufci1ZyoD/wV2TYMKxXUoNuoqwy+CkgzAiQ== + dependencies: + unist-util-is "^4.0.0" + unist-util-generated@^1.0.0: version "1.1.6" resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b"