diff --git a/packages/components/README.md b/packages/components/README.md
index ad35c67f..03eb5750 100644
--- a/packages/components/README.md
+++ b/packages/components/README.md
@@ -1,9 +1,9 @@
[![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-components.svg)](https://www.npmjs.com/package/@quri/squiggle-components)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/quantified-uncertainty/squiggle/blob/develop/LICENSE)
-# Squiggle Components
+# Squiggle components
-This package contains all the components for squiggle. These can be used either as a library or hosted as a [storybook](https://storybook.js.org/).
+This package contains the react components for squiggle. These can be used either as a library or hosted as a [storybook](https://storybook.js.org/).
# Usage in a `react` project
@@ -17,7 +17,10 @@ Add to `App.js`:
```jsx
import { SquiggleEditor } from "@quri/squiggle-components";
-;
+;
```
# Build storybook for development
@@ -38,9 +41,3 @@ Run a development server
```sh
yarn start
```
-
-And build artefacts for production,
-
-```sh
-yarn build # builds storybook app
-```
diff --git a/packages/components/package.json b/packages/components/package.json
index de8efb96..4888a0a5 100644
--- a/packages/components/package.json
+++ b/packages/components/package.json
@@ -1,19 +1,19 @@
{
"name": "@quri/squiggle-components",
- "version": "0.2.14",
+ "version": "0.2.17",
"license": "MIT",
"dependencies": {
- "react-ace": "10.1.0",
- "@quri/squiggle-lang": "^0.2.7",
- "react-dom": "^18.1.0",
- "vega": "^5.22.1",
- "vega-embed": "^6.20.6",
- "vega-lite": "^5.2.0",
- "react-vega": "^7.5.0",
- "react": "^18.1.0",
+ "@quri/squiggle-lang": "^0.2.8",
"@react-hook/size": "^2.1.2",
"lodash": "^4.17.21",
- "styled-components": "^5.3.5"
+ "react": "^18.1.0",
+ "react-ace": "^10.1.0",
+ "react-dom": "^18.1.0",
+ "react-vega": "^7.5.0",
+ "styled-components": "^5.3.5",
+ "vega": "^5.22.1",
+ "vega-embed": "^6.20.6",
+ "vega-lite": "^5.2.0"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
@@ -25,36 +25,35 @@
"@storybook/node-logger": "^6.4.22",
"@storybook/preset-create-react-app": "^4.1.0",
"@storybook/react": "^6.4.22",
- "@types/styled-components": "^5.1.24",
- "@types/webpack": "^5.28.0",
- "style-loader": "^3.3.1",
- "ts-loader": "^9.2.9",
- "webpack": "^5.72.0",
- "webpack-cli": "^4.9.2",
- "webpack-dev-server": "^4.8.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^14.1.1",
"@types/jest": "^27.4.0",
- "web-vitals": "^2.1.4",
"@types/lodash": "^4.14.182",
"@types/node": "^17.0.29",
"@types/react": "^18.0.3",
"@types/react-dom": "^18.0.2",
+ "@types/styled-components": "^5.1.24",
+ "@types/webpack": "^5.28.0",
"cross-env": "^7.0.3",
- "react-scripts": "5.0.1",
+ "react-scripts": "^5.0.1",
+ "style-loader": "^3.3.1",
+ "ts-loader": "^9.2.9",
"tsconfig-paths-webpack-plugin": "^3.5.2",
"typescript": "^4.6.3",
- "webpack-cli": "^4.9.2"
+ "web-vitals": "^2.1.4",
+ "webpack": "^5.72.0",
+ "webpack-cli": "^4.9.2",
+ "webpack-dev-server": "^4.8.1"
},
"scripts": {
"start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
"build": "tsc -b && build-storybook -s public",
- "build:package": "tsc -b",
"bundle": "webpack",
"all": "yarn bundle && yarn build",
"lint": "prettier --check .",
- "format": "prettier --write ."
+ "format": "prettier --write .",
+ "prepack": "yarn bundle && tsc -b"
},
"eslintConfig": {
"extends": [
@@ -88,7 +87,6 @@
"@types/react": "17.0.43"
},
"source": "./src/index.ts",
- "browser": "dist/bundle.js",
- "main": "dist/src/index.js",
- "types": "dist/src/index.d.ts"
+ "main": "./dist/src/index.js",
+ "types": "./dist/src/index.d.ts"
}
diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx
index 8730beaa..699a7e28 100644
--- a/packages/components/src/components/SquiggleChart.tsx
+++ b/packages/components/src/components/SquiggleChart.tsx
@@ -3,16 +3,17 @@ import _ from "lodash";
import styled from "styled-components";
import {
run,
- runPartial,
errorValueToString,
squiggleExpression,
bindings,
samplingParams,
+ jsImports,
+ defaultImports,
+ defaultBindings,
} from "@quri/squiggle-lang";
import { NumberShower } from "./NumberShower";
import { DistributionChart } from "./DistributionChart";
import { ErrorBox } from "./ErrorBox";
-import useSize from "@react-hook/size";
const variableBox = {
Component: styled.div`
@@ -143,8 +144,6 @@ export interface SquiggleChartProps {
diagramStop?: number;
/** If the result is a function, how many points along the function it samples */
diagramCount?: number;
- /** variables declared before this expression */
- environment?: unknown;
/** When the environment changes */
onChange?(expr: squiggleExpression): void;
/** CSS width of the element */
@@ -152,6 +151,8 @@ export interface SquiggleChartProps {
height?: number;
/** Bindings of previous variables declared */
bindings?: bindings;
+ /** JS imported parameters */
+ jsImports?: jsImports;
}
const ChartWrapper = styled.div`
@@ -166,14 +167,20 @@ export const SquiggleChart: React.FC = ({
outputXYPoints = 1000,
onChange = () => {},
height = 60,
- bindings = {},
+ bindings = defaultBindings,
+ jsImports = defaultImports,
width = NaN,
}: SquiggleChartProps) => {
let samplingInputs: samplingParams = {
sampleCount: sampleCount,
xyPointLength: outputXYPoints,
};
- let expressionResult = run(squiggleString, bindings, samplingInputs);
+ let expressionResult = run(
+ squiggleString,
+ bindings,
+ samplingInputs,
+ jsImports
+ );
let internal: JSX.Element;
if (expressionResult.tag === "Ok") {
let expression = expressionResult.value;
diff --git a/packages/components/src/components/SquiggleEditor.tsx b/packages/components/src/components/SquiggleEditor.tsx
index f85cf1e8..23686a4f 100644
--- a/packages/components/src/components/SquiggleEditor.tsx
+++ b/packages/components/src/components/SquiggleEditor.tsx
@@ -3,8 +3,18 @@ import * as ReactDOM from "react-dom";
import { SquiggleChart } from "./SquiggleChart";
import { CodeEditor } from "./CodeEditor";
import styled from "styled-components";
-import type { squiggleExpression, bindings } from "@quri/squiggle-lang";
-import { runPartial, errorValueToString } from "@quri/squiggle-lang";
+import type {
+ squiggleExpression,
+ samplingParams,
+ bindings,
+ jsImports,
+} from "@quri/squiggle-lang";
+import {
+ runPartial,
+ errorValueToString,
+ defaultImports,
+ defaultBindings,
+} from "@quri/squiggle-lang";
import { ErrorBox } from "./ErrorBox";
export interface SquiggleEditorProps {
@@ -22,14 +32,14 @@ export interface SquiggleEditorProps {
diagramStop?: number;
/** If the result is a function, how many points along the function it samples */
diagramCount?: number;
- /** The environment, other variables that were already declared */
- environment?: unknown;
/** when the environment changes. Used again for notebook magic*/
onChange?(expr: squiggleExpression): void;
/** The width of the element */
- width: number;
+ width?: number;
/** Previous variable declarations */
- bindings: bindings;
+ bindings?: bindings;
+ /** JS Imports */
+ jsImports?: jsImports;
}
const Input = styled.div`
@@ -49,8 +59,8 @@ export let SquiggleEditor: React.FC = ({
diagramStop,
diagramCount,
onChange,
- environment,
- bindings = {},
+ bindings = defaultBindings,
+ jsImports = defaultImports,
}: SquiggleEditorProps) => {
let [expression, setExpression] = React.useState(initialSquiggleString);
return (
@@ -74,9 +84,9 @@ export let SquiggleEditor: React.FC = ({
diagramStart={diagramStart}
diagramStop={diagramStop}
diagramCount={diagramCount}
- environment={environment}
onChange={onChange}
bindings={bindings}
+ jsImports={jsImports}
/>
);
@@ -131,19 +141,31 @@ export interface SquigglePartialProps {
diagramCount?: number;
/** when the environment changes. Used again for notebook magic*/
onChange?(expr: bindings): void;
- /** The width of the element */
- width: number;
/** Previously declared variables */
- bindings: bindings;
+ bindings?: bindings;
+ /** Variables imported from js */
+ jsImports?: jsImports;
}
export let SquigglePartial: React.FC = ({
initialSquiggleString = "",
onChange,
- bindings,
+ bindings = defaultBindings,
+ sampleCount = 1000,
+ outputXYPoints = 1000,
+ jsImports = defaultImports,
}: SquigglePartialProps) => {
+ let samplingInputs: samplingParams = {
+ sampleCount: sampleCount,
+ xyPointLength: outputXYPoints,
+ };
let [expression, setExpression] = React.useState(initialSquiggleString);
- let squiggleResult = runPartial(expression, bindings);
+ let squiggleResult = runPartial(
+ expression,
+ bindings,
+ samplingInputs,
+ jsImports
+ );
if (squiggleResult.tag == "Ok") {
if (onChange) onChange(squiggleResult.value);
}
diff --git a/packages/components/src/vega-specs/spec-distributions.json b/packages/components/src/vega-specs/spec-distributions.json
index 129183a5..5b6ed261 100644
--- a/packages/components/src/vega-specs/spec-distributions.json
+++ b/packages/components/src/vega-specs/spec-distributions.json
@@ -88,7 +88,7 @@
"tickOpacity": 0.0,
"domainColor": "#fff",
"domainOpacity": 0.0,
- "format": "~s",
+ "format": "~g",
"tickCount": 10
}
],
diff --git a/packages/squiggle-lang/README.md b/packages/squiggle-lang/README.md
index 05bb969c..f6735454 100644
--- a/packages/squiggle-lang/README.md
+++ b/packages/squiggle-lang/README.md
@@ -3,7 +3,26 @@
# Squiggle language
-## Build for development
+_An estimation language_
+
+# Use the `npm` package
+
+For instance, in a javascript project, you can
+
+```sh
+yarn add @quri/squiggle-lang
+```
+
+```js
+import { run } from "@quri/squiggle-lang";
+run(
+ "normal(0, 1) * fromSamples([-3,-2,-1,1,2,3,3,3,4,9]"
+).value.value.toSparkline().value;
+```
+
+**However, for most use cases you'll prefer to use our [library of react components](https://www.npmjs.com/package/@quri/squiggle-components)**, and let your app transitively depend on `@quri/squiggle-lang`.
+
+# Build for development
We assume that you ran `yarn` at the monorepo level.
@@ -23,7 +42,7 @@ yarn test
yarn coverage:rescript; o _coverage/index.html # produces coverage report and opens it in browser
```
-## Distributing this package or using this package from other monorepo packages
+# Distributing this package or using this package from other monorepo packages
As it says in the other `packages/*/README.md`s, building this package is an essential step of building other packages.
diff --git a/packages/squiggle-lang/__tests__/TS/JS_test.ts b/packages/squiggle-lang/__tests__/TS/JS_test.ts
index e522eb95..76871fc8 100644
--- a/packages/squiggle-lang/__tests__/TS/JS_test.ts
+++ b/packages/squiggle-lang/__tests__/TS/JS_test.ts
@@ -1,4 +1,4 @@
-import { Distribution, resultMap } from "../../src/js/index";
+import { Distribution, resultMap, defaultBindings } from "../../src/js/index";
import { testRun, testRunPartial } from "./TestHelpers";
function Ok(x: b) {
@@ -68,6 +68,28 @@ describe("Partials", () => {
});
});
+describe("JS Imports", () => {
+ test("Can pass parameters into partials and cells", () => {
+ let bindings = testRunPartial(`y = $x + 2`, defaultBindings, { x: 1 });
+ let bindings2 = testRunPartial(`z = y + $a`, bindings, { a: 3 });
+ expect(testRun(`z`, bindings2)).toEqual({
+ tag: "number",
+ value: 6,
+ });
+ });
+ test("Complicated deep parameters", () => {
+ expect(
+ testRun(`$x.y[0][0].w + $x.z + $u.v`, defaultBindings, {
+ x: { y: [[{ w: 1 }]], z: 2 },
+ u: { v: 3 },
+ })
+ ).toEqual({
+ tag: "number",
+ value: 6,
+ });
+ });
+});
+
describe("Distribution", () => {
//It's important that sampleCount is less than 9. If it's more, than that will create randomness
//Also, note, the value should be created using makeSampleSetDist() later on.
diff --git a/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts b/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts
index a617010b..2c77e210 100644
--- a/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts
+++ b/packages/squiggle-lang/__tests__/TS/SampleSet_test.ts
@@ -1,5 +1,5 @@
import { Distribution } from "../../src/js/index";
-import { expectErrorToBeBounded, failDefault } from "./TestHelpers";
+import { expectErrorToBeBounded, failDefault, testRun } from "./TestHelpers";
import * as fc from "fast-check";
// Beware: float64Array makes it appear in an infinite loop.
@@ -212,3 +212,18 @@ describe("mean is mean", () => {
);
});
});
+
+describe("fromSamples function", () => {
+ test.skip("gives a mean near the mean of the input", () => {
+ fc.assert(
+ fc.property(arrayGen(), (xs_) => {
+ let xs = Array.from(xs_);
+ let xsString = xs.toString();
+ let squiggleString = `x = fromSamples([${xsString}]); mean(x)`;
+ let squiggleResult = testRun(squiggleString);
+ let mean = xs.reduce((a, b) => a + b, 0.0) / xs.length;
+ expect(squiggleResult.value).toBeCloseTo(mean, 4);
+ })
+ );
+ });
+});
diff --git a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts
index 7d51c98e..d9d8444f 100644
--- a/packages/squiggle-lang/__tests__/TS/TestHelpers.ts
+++ b/packages/squiggle-lang/__tests__/TS/TestHelpers.ts
@@ -4,14 +4,25 @@ import {
bindings,
squiggleExpression,
errorValueToString,
+ defaultImports,
+ defaultBindings,
+ jsImports,
} from "../../src/js/index";
-export function testRun(x: string, bindings = {}): squiggleExpression {
- let squiggleResult = run(x, bindings, {
- sampleCount: 1000,
- xyPointLength: 100,
- });
- // return squiggleResult.value
+export function testRun(
+ x: string,
+ bindings: bindings = defaultBindings,
+ imports: jsImports = defaultImports
+): squiggleExpression {
+ let squiggleResult = run(
+ x,
+ bindings,
+ {
+ sampleCount: 1000,
+ xyPointLength: 100,
+ },
+ imports
+ );
if (squiggleResult.tag === "Ok") {
return squiggleResult.value;
} else {
@@ -23,11 +34,20 @@ export function testRun(x: string, bindings = {}): squiggleExpression {
}
}
-export function testRunPartial(x: string, bindings: bindings = {}): bindings {
- let squiggleResult = runPartial(x, bindings, {
- sampleCount: 1000,
- xyPointLength: 100,
- });
+export function testRunPartial(
+ x: string,
+ bindings: bindings = defaultBindings,
+ imports: jsImports = defaultImports
+): bindings {
+ let squiggleResult = runPartial(
+ x,
+ bindings,
+ {
+ sampleCount: 1000,
+ xyPointLength: 100,
+ },
+ imports
+ );
if (squiggleResult.tag === "Ok") {
return squiggleResult.value;
} else {
diff --git a/packages/squiggle-lang/package.json b/packages/squiggle-lang/package.json
index 4d146ef8..40f7e7c7 100644
--- a/packages/squiggle-lang/package.json
+++ b/packages/squiggle-lang/package.json
@@ -1,6 +1,6 @@
{
"name": "@quri/squiggle-lang",
- "version": "0.2.7",
+ "version": "0.2.8",
"homepage": "https://squiggle-language.com",
"license": "MIT",
"scripts": {
@@ -24,6 +24,7 @@
"format:rescript": "rescript format -all",
"format:prettier": "prettier --write .",
"format": "yarn format:rescript && yarn format:prettier",
+ "prepack": "yarn build && yarn test && yarn bundle",
"all": "yarn build && yarn bundle && yarn test"
},
"keywords": [
@@ -35,22 +36,22 @@
"rescript": "^9.1.4",
"jstat": "^1.9.5",
"pdfast": "^0.2.0",
- "mathjs": "10.5.0"
+ "mathjs": "^10.5.0"
},
"devDependencies": {
"bisect_ppx": "^2.7.1",
- "lodash": "4.17.21",
+ "lodash": "^4.17.21",
"rescript-fast-check": "^1.1.1",
"@glennsl/rescript-jest": "^0.9.0",
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@types/jest": "^27.4.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"chalk": "^5.0.1",
- "codecov": "3.8.3",
- "fast-check": "2.25.0",
+ "codecov": "^3.8.3",
+ "fast-check": "^2.25.0",
"gentype": "^4.3.0",
"jest": "^27.5.1",
- "moduleserve": "0.9.1",
+ "moduleserve": "^0.9.1",
"nyc": "^15.1.0",
"reanalyze": "^2.19.0",
"ts-jest": "^27.1.4",
diff --git a/packages/squiggle-lang/src/js/distribution.ts b/packages/squiggle-lang/src/js/distribution.ts
new file mode 100644
index 00000000..603dfaa9
--- /dev/null
+++ b/packages/squiggle-lang/src/js/distribution.ts
@@ -0,0 +1,247 @@
+import * as _ from "lodash";
+import {
+ genericDist,
+ continuousShape,
+ discreteShape,
+ samplingParams,
+ distributionError,
+ toPointSet,
+ distributionErrorToString,
+} from "../rescript/TypescriptInterface.gen";
+import { result, resultMap, Ok } from "./types";
+import {
+ Constructors_mean,
+ Constructors_sample,
+ Constructors_pdf,
+ Constructors_cdf,
+ Constructors_inv,
+ Constructors_normalize,
+ Constructors_isNormalized,
+ Constructors_toPointSet,
+ Constructors_toSampleSet,
+ Constructors_truncate,
+ Constructors_inspect,
+ Constructors_toString,
+ Constructors_toSparkline,
+ Constructors_algebraicAdd,
+ Constructors_algebraicMultiply,
+ Constructors_algebraicDivide,
+ Constructors_algebraicSubtract,
+ Constructors_algebraicLogarithm,
+ Constructors_algebraicPower,
+ Constructors_pointwiseAdd,
+ Constructors_pointwiseMultiply,
+ Constructors_pointwiseDivide,
+ Constructors_pointwiseSubtract,
+ Constructors_pointwiseLogarithm,
+ Constructors_pointwisePower,
+} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
+
+export type point = { x: number; y: number };
+
+function shapePoints(x: continuousShape | discreteShape): point[] {
+ let xs = x.xyShape.xs;
+ let ys = x.xyShape.ys;
+ return _.zipWith(xs, ys, (x, y) => ({ x, y }));
+}
+export type shape = {
+ continuous: point[];
+ discrete: point[];
+};
+
+export class Distribution {
+ t: genericDist;
+ env: samplingParams;
+
+ constructor(t: genericDist, env: samplingParams) {
+ this.t = t;
+ this.env = env;
+ return this;
+ }
+
+ mapResultDist(
+ r: result
+ ): result {
+ return resultMap(r, (v: genericDist) => new Distribution(v, this.env));
+ }
+
+ mean(): result {
+ return Constructors_mean({ env: this.env }, this.t);
+ }
+
+ sample(): result {
+ return Constructors_sample({ env: this.env }, this.t);
+ }
+
+ pdf(n: number): result {
+ return Constructors_pdf({ env: this.env }, this.t, n);
+ }
+
+ cdf(n: number): result {
+ return Constructors_cdf({ env: this.env }, this.t, n);
+ }
+
+ inv(n: number): result {
+ return Constructors_inv({ env: this.env }, this.t, n);
+ }
+
+ isNormalized(): result {
+ return Constructors_isNormalized({ env: this.env }, this.t);
+ }
+
+ normalize(): result {
+ return this.mapResultDist(
+ Constructors_normalize({ env: this.env }, this.t)
+ );
+ }
+
+ type() {
+ return this.t.tag;
+ }
+
+ pointSet(): result {
+ let pointSet = toPointSet(
+ this.t,
+ {
+ xyPointLength: this.env.xyPointLength,
+ sampleCount: this.env.sampleCount,
+ },
+ undefined
+ );
+ if (pointSet.tag === "Ok") {
+ let distribution = pointSet.value;
+ if (distribution.tag === "Continuous") {
+ return Ok({
+ continuous: shapePoints(distribution.value),
+ discrete: [],
+ });
+ } else if (distribution.tag === "Discrete") {
+ return Ok({
+ discrete: shapePoints(distribution.value),
+ continuous: [],
+ });
+ } else {
+ return Ok({
+ discrete: shapePoints(distribution.value.discrete),
+ continuous: shapePoints(distribution.value.continuous),
+ });
+ }
+ } else {
+ return pointSet;
+ }
+ }
+
+ toPointSet(): result {
+ return this.mapResultDist(
+ Constructors_toPointSet({ env: this.env }, this.t)
+ );
+ }
+
+ toSampleSet(n: number): result {
+ return this.mapResultDist(
+ Constructors_toSampleSet({ env: this.env }, this.t, n)
+ );
+ }
+
+ truncate(
+ left: number,
+ right: number
+ ): result {
+ return this.mapResultDist(
+ Constructors_truncate({ env: this.env }, this.t, left, right)
+ );
+ }
+
+ inspect(): result {
+ return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t));
+ }
+
+ toString(): string {
+ let result = Constructors_toString({ env: this.env }, this.t);
+ if (result.tag === "Ok") {
+ return result.value;
+ } else {
+ return distributionErrorToString(result.value);
+ }
+ }
+
+ toSparkline(n: number): result {
+ return Constructors_toSparkline({ env: this.env }, this.t, n);
+ }
+
+ algebraicAdd(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_algebraicAdd({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ algebraicMultiply(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ algebraicDivide(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_algebraicDivide({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ algebraicSubtract(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ algebraicLogarithm(
+ d2: Distribution
+ ): result {
+ return this.mapResultDist(
+ Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ algebraicPower(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_algebraicPower({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ pointwiseAdd(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ pointwiseMultiply(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ pointwiseDivide(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ pointwiseSubtract(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ pointwiseLogarithm(
+ d2: Distribution
+ ): result {
+ return this.mapResultDist(
+ Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t)
+ );
+ }
+
+ pointwisePower(d2: Distribution): result {
+ return this.mapResultDist(
+ Constructors_pointwisePower({ env: this.env }, this.t, d2.t)
+ );
+ }
+}
diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts
index 34318424..baccded3 100644
--- a/packages/squiggle-lang/src/js/index.ts
+++ b/packages/squiggle-lang/src/js/index.ts
@@ -1,6 +1,5 @@
import * as _ from "lodash";
import {
- genericDist,
samplingParams,
evaluatePartialUsingExternalBindings,
externalBindings,
@@ -21,34 +20,23 @@ export {
errorValueToString,
distributionErrorToString,
} from "../rescript/TypescriptInterface.gen";
+export type {
+ samplingParams,
+ errorValue,
+ externalBindings as bindings,
+ jsImports,
+};
import {
- Constructors_mean,
- Constructors_sample,
- Constructors_pdf,
- Constructors_cdf,
- Constructors_inv,
- Constructors_normalize,
- Constructors_isNormalized,
- Constructors_toPointSet,
- Constructors_toSampleSet,
- Constructors_truncate,
- Constructors_inspect,
- Constructors_toString,
- Constructors_toSparkline,
- Constructors_algebraicAdd,
- Constructors_algebraicMultiply,
- Constructors_algebraicDivide,
- Constructors_algebraicSubtract,
- Constructors_algebraicLogarithm,
- Constructors_algebraicPower,
- Constructors_pointwiseAdd,
- Constructors_pointwiseMultiply,
- Constructors_pointwiseDivide,
- Constructors_pointwiseSubtract,
- Constructors_pointwiseLogarithm,
- Constructors_pointwisePower,
-} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
-export type { samplingParams, errorValue, externalBindings as bindings };
+ jsValueToBinding,
+ jsValue,
+ rescriptExport,
+ squiggleExpression,
+ convertRawToTypescript,
+} from "./rescript_interop";
+import { result, resultMap, tag, tagged } from "./types";
+import { Distribution } from "./distribution";
+
+export { Distribution, squiggleExpression, result, resultMap };
export let defaultSamplingInputs: samplingParams = {
sampleCount: 10000,
@@ -100,27 +88,54 @@ export type squiggleExpression =
export function run(
squiggleString: string,
bindings?: externalBindings,
- samplingInputs?: samplingParams
+ samplingInputs?: samplingParams,
+ imports?: jsImports
): result {
- let b = bindings ? bindings : {};
+ let b = bindings ? bindings : defaultBindings;
+ let i = imports ? imports : defaultImports;
let si: samplingParams = samplingInputs
? samplingInputs
: defaultSamplingInputs;
let result: result =
- evaluateUsingExternalBindings(squiggleString, b);
+ evaluateUsingExternalBindings(squiggleString, mergeImports(b, i));
return resultMap(result, (x) => createTsExport(x, si));
}
// Run Partial. A partial is a block of code that doesn't return a value
export function runPartial(
squiggleString: string,
- bindings: externalBindings,
- _samplingInputs?: samplingParams
+ bindings?: externalBindings,
+ _samplingInputs?: samplingParams,
+ imports?: jsImports
): result {
- return evaluatePartialUsingExternalBindings(squiggleString, bindings);
+ let b = bindings ? bindings : defaultBindings;
+ let i = imports ? imports : defaultImports;
+
+ return evaluatePartialUsingExternalBindings(
+ squiggleString,
+ mergeImports(b, i)
+ );
}
+function mergeImports(
+ bindings: externalBindings,
+ imports: jsImports
+): externalBindings {
+ let transformedImports = Object.fromEntries(
+ Object.entries(imports).map(([key, value]) => [
+ "$" + key,
+ jsValueToBinding(value),
+ ])
+ );
+ return _.merge(bindings, transformedImports);
+}
+
+type jsImports = { [key: string]: jsValue };
+
+export let defaultImports: jsImports = {};
+export let defaultBindings: externalBindings = {};
+
function createTsExport(
x: expressionValue,
sampEnv: samplingParams
@@ -183,329 +198,3 @@ function createTsExport(
return tag("symbol", x.value);
}
}
-
-// Helper functions to convert the rescript representations that genType doesn't
-// cover
-function convertRawToTypescript(
- result: rescriptExport,
- sampEnv: samplingParams
-): squiggleExpression {
- switch (result.TAG) {
- case 0: // EvArray
- return tag(
- "array",
- result._0.map((x) => convertRawToTypescript(x, sampEnv))
- );
- case 1: // EvBool
- return tag("boolean", result._0);
- case 2: // EvCall
- return tag("call", result._0);
- case 3: // EvDistribution
- return tag(
- "distribution",
- new Distribution(
- convertRawDistributionToGenericDist(result._0),
- sampEnv
- )
- );
- case 4: // EvNumber
- return tag("number", result._0);
- case 5: // EvRecord
- return tag(
- "record",
- _.mapValues(result._0, (x) => convertRawToTypescript(x, sampEnv))
- );
- case 6: // EvString
- return tag("string", result._0);
- case 7: // EvSymbol
- return tag("symbol", result._0);
- }
-}
-
-function convertRawDistributionToGenericDist(
- result: rescriptDist
-): genericDist {
- switch (result.TAG) {
- case 0: // Point Set Dist
- switch (result._0.TAG) {
- case 0: // Mixed
- return tag("PointSet", tag("Mixed", result._0._0));
- case 1: // Discrete
- return tag("PointSet", tag("Discrete", result._0._0));
- case 2: // Continuous
- return tag("PointSet", tag("Continuous", result._0._0));
- }
- case 1: // Sample Set Dist
- return tag("SampleSet", result._0);
- case 2: // Symbolic Dist
- return tag("Symbolic", result._0);
- }
-}
-
-// Raw rescript types.
-type rescriptExport =
- | {
- TAG: 0; // EvArray
- _0: rescriptExport[];
- }
- | {
- TAG: 1; // EvBool
- _0: boolean;
- }
- | {
- TAG: 2; // EvCall
- _0: string;
- }
- | {
- TAG: 3; // EvDistribution
- _0: rescriptDist;
- }
- | {
- TAG: 4; // EvNumber
- _0: number;
- }
- | {
- TAG: 5; // EvRecord
- _0: { [key: string]: rescriptExport };
- }
- | {
- TAG: 6; // EvString
- _0: string;
- }
- | {
- TAG: 7; // EvSymbol
- _0: string;
- };
-
-type rescriptDist =
- | { TAG: 0; _0: rescriptPointSetDist }
- | { TAG: 1; _0: sampleSetDist }
- | { TAG: 2; _0: symbolicDist };
-
-type rescriptPointSetDist =
- | {
- TAG: 0; // Mixed
- _0: mixedShape;
- }
- | {
- TAG: 1; // Discrete
- _0: discreteShape;
- }
- | {
- TAG: 2; // ContinuousShape
- _0: continuousShape;
- };
-
-export function resultExn(r: result): a | c {
- return r.value;
-}
-
-export type point = { x: number; y: number };
-
-export type shape = {
- continuous: point[];
- discrete: point[];
-};
-
-function shapePoints(x: continuousShape | discreteShape): point[] {
- let xs = x.xyShape.xs;
- let ys = x.xyShape.ys;
- return _.zipWith(xs, ys, (x, y) => ({ x, y }));
-}
-
-export class Distribution {
- t: genericDist;
- env: samplingParams;
-
- constructor(t: genericDist, env: samplingParams) {
- this.t = t;
- this.env = env;
- return this;
- }
-
- mapResultDist(
- r: result
- ): result {
- return resultMap(r, (v: genericDist) => new Distribution(v, this.env));
- }
-
- mean(): result {
- return Constructors_mean({ env: this.env }, this.t);
- }
-
- sample(): result {
- return Constructors_sample({ env: this.env }, this.t);
- }
-
- pdf(n: number): result {
- return Constructors_pdf({ env: this.env }, this.t, n);
- }
-
- cdf(n: number): result {
- return Constructors_cdf({ env: this.env }, this.t, n);
- }
-
- inv(n: number): result {
- return Constructors_inv({ env: this.env }, this.t, n);
- }
-
- isNormalized(): result {
- return Constructors_isNormalized({ env: this.env }, this.t);
- }
-
- normalize(): result {
- return this.mapResultDist(
- Constructors_normalize({ env: this.env }, this.t)
- );
- }
-
- type() {
- return this.t.tag;
- }
-
- pointSet(): result {
- let pointSet = toPointSet(
- this.t,
- {
- xyPointLength: this.env.xyPointLength,
- sampleCount: this.env.sampleCount,
- },
- undefined
- );
- if (pointSet.tag === "Ok") {
- let distribution = pointSet.value;
- if (distribution.tag === "Continuous") {
- return Ok({
- continuous: shapePoints(distribution.value),
- discrete: [],
- });
- } else if (distribution.tag === "Discrete") {
- return Ok({
- discrete: shapePoints(distribution.value),
- continuous: [],
- });
- } else {
- return Ok({
- discrete: shapePoints(distribution.value.discrete),
- continuous: shapePoints(distribution.value.continuous),
- });
- }
- } else {
- return pointSet;
- }
- }
-
- toPointSet(): result {
- return this.mapResultDist(
- Constructors_toPointSet({ env: this.env }, this.t)
- );
- }
-
- toSampleSet(n: number): result {
- return this.mapResultDist(
- Constructors_toSampleSet({ env: this.env }, this.t, n)
- );
- }
-
- truncate(
- left: number,
- right: number
- ): result {
- return this.mapResultDist(
- Constructors_truncate({ env: this.env }, this.t, left, right)
- );
- }
-
- inspect(): result {
- return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t));
- }
-
- toString(): string {
- let result = Constructors_toString({ env: this.env }, this.t);
- if (result.tag === "Ok") {
- return result.value;
- } else {
- return distributionErrorToString(result.value);
- }
- }
-
- toSparkline(n: number): result {
- return Constructors_toSparkline({ env: this.env }, this.t, n);
- }
-
- algebraicAdd(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_algebraicAdd({ env: this.env }, this.t, d2.t)
- );
- }
-
- algebraicMultiply(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t)
- );
- }
-
- algebraicDivide(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_algebraicDivide({ env: this.env }, this.t, d2.t)
- );
- }
-
- algebraicSubtract(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t)
- );
- }
-
- algebraicLogarithm(
- d2: Distribution
- ): result {
- return this.mapResultDist(
- Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t)
- );
- }
-
- algebraicPower(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_algebraicPower({ env: this.env }, this.t, d2.t)
- );
- }
-
- pointwiseAdd(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t)
- );
- }
-
- pointwiseMultiply(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t)
- );
- }
-
- pointwiseDivide(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t)
- );
- }
-
- pointwiseSubtract(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t)
- );
- }
-
- pointwiseLogarithm(
- d2: Distribution
- ): result {
- return this.mapResultDist(
- Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t)
- );
- }
-
- pointwisePower(d2: Distribution): result {
- return this.mapResultDist(
- Constructors_pointwisePower({ env: this.env }, this.t, d2.t)
- );
- }
-}
diff --git a/packages/squiggle-lang/src/js/rescript_interop.ts b/packages/squiggle-lang/src/js/rescript_interop.ts
new file mode 100644
index 00000000..b017699f
--- /dev/null
+++ b/packages/squiggle-lang/src/js/rescript_interop.ts
@@ -0,0 +1,155 @@
+import * as _ from "lodash";
+import {
+ mixedShape,
+ sampleSetDist,
+ genericDist,
+ samplingParams,
+ symbolicDist,
+ discreteShape,
+ continuousShape,
+} from "../rescript/TypescriptInterface.gen";
+import { Distribution } from "./distribution";
+import { tagged, tag } from "./types";
+// This file is here to compensate for genType not fully recursively converting types
+
+// Raw rescript types.
+export type rescriptExport =
+ | {
+ TAG: 0; // EvArray
+ _0: rescriptExport[];
+ }
+ | {
+ TAG: 1; // EvBool
+ _0: boolean;
+ }
+ | {
+ TAG: 2; // EvCall
+ _0: string;
+ }
+ | {
+ TAG: 3; // EvDistribution
+ _0: rescriptDist;
+ }
+ | {
+ TAG: 4; // EvNumber
+ _0: number;
+ }
+ | {
+ TAG: 5; // EvRecord
+ _0: { [key: string]: rescriptExport };
+ }
+ | {
+ TAG: 6; // EvString
+ _0: string;
+ }
+ | {
+ TAG: 7; // EvSymbol
+ _0: string;
+ };
+
+type rescriptDist =
+ | { TAG: 0; _0: rescriptPointSetDist }
+ | { TAG: 1; _0: sampleSetDist }
+ | { TAG: 2; _0: symbolicDist };
+
+type rescriptPointSetDist =
+ | {
+ TAG: 0; // Mixed
+ _0: mixedShape;
+ }
+ | {
+ TAG: 1; // Discrete
+ _0: discreteShape;
+ }
+ | {
+ TAG: 2; // ContinuousShape
+ _0: continuousShape;
+ };
+
+export type squiggleExpression =
+ | tagged<"symbol", string>
+ | tagged<"string", string>
+ | tagged<"call", string>
+ | tagged<"array", squiggleExpression[]>
+ | tagged<"boolean", boolean>
+ | tagged<"distribution", Distribution>
+ | tagged<"number", number>
+ | tagged<"record", { [key: string]: squiggleExpression }>;
+
+export function convertRawToTypescript(
+ result: rescriptExport,
+ sampEnv: samplingParams
+): squiggleExpression {
+ switch (result.TAG) {
+ case 0: // EvArray
+ return tag(
+ "array",
+ result._0.map((x) => convertRawToTypescript(x, sampEnv))
+ );
+ case 1: // EvBool
+ return tag("boolean", result._0);
+ case 2: // EvCall
+ return tag("call", result._0);
+ case 3: // EvDistribution
+ return tag(
+ "distribution",
+ new Distribution(
+ convertRawDistributionToGenericDist(result._0),
+ sampEnv
+ )
+ );
+ case 4: // EvNumber
+ return tag("number", result._0);
+ case 5: // EvRecord
+ return tag(
+ "record",
+ _.mapValues(result._0, (x) => convertRawToTypescript(x, sampEnv))
+ );
+ case 6: // EvString
+ return tag("string", result._0);
+ case 7: // EvSymbol
+ return tag("symbol", result._0);
+ }
+}
+
+function convertRawDistributionToGenericDist(
+ result: rescriptDist
+): genericDist {
+ switch (result.TAG) {
+ case 0: // Point Set Dist
+ switch (result._0.TAG) {
+ case 0: // Mixed
+ return tag("PointSet", tag("Mixed", result._0._0));
+ case 1: // Discrete
+ return tag("PointSet", tag("Discrete", result._0._0));
+ case 2: // Continuous
+ return tag("PointSet", tag("Continuous", result._0._0));
+ }
+ case 1: // Sample Set Dist
+ return tag("SampleSet", result._0);
+ case 2: // Symbolic Dist
+ return tag("Symbolic", result._0);
+ }
+}
+
+export type jsValue =
+ | string
+ | number
+ | jsValue[]
+ | { [key: string]: jsValue }
+ | boolean;
+
+export function jsValueToBinding(value: jsValue): rescriptExport {
+ if (typeof value === "boolean") {
+ return { TAG: 1, _0: value as boolean };
+ } else if (typeof value === "string") {
+ return { TAG: 6, _0: value as string };
+ } else if (typeof value === "number") {
+ return { TAG: 4, _0: value as number };
+ } else if (Array.isArray(value)) {
+ return { TAG: 0, _0: value.map(jsValueToBinding) };
+ } else {
+ // Record
+ return { TAG: 5, _0: _.mapValues(value, jsValueToBinding) };
+ }
+}
diff --git a/packages/squiggle-lang/src/js/types.ts b/packages/squiggle-lang/src/js/types.ts
new file mode 100644
index 00000000..8851b520
--- /dev/null
+++ b/packages/squiggle-lang/src/js/types.ts
@@ -0,0 +1,30 @@
+export type result =
+ | {
+ tag: "Ok";
+ value: a;
+ }
+ | {
+ tag: "Error";
+ value: b;
+ };
+
+export function resultMap(
+ r: result,
+ mapFn: (x: a) => b
+): result {
+ if (r.tag === "Ok") {
+ return { tag: "Ok", value: mapFn(r.value) };
+ } else {
+ return r;
+ }
+}
+
+export function Ok(x: a): result {
+ return { tag: "Ok", value: x };
+}
+
+export type tagged = { tag: a; value: b };
+
+export function tag(x: a, y: b): tagged {
+ return { tag: x, value: y };
+}
diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res
index 18ee2d6a..5f07c6a8 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.res
@@ -154,6 +154,16 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => {
->GenericDist.toPointSet(~xyPointLength, ~sampleCount, ())
->E.R2.fmap(r => Dist(PointSet(r)))
->OutputLocal.fromResult
+ | ToDist(Scale(#Logarithm, f)) =>
+ dist
+ ->GenericDist.pointwiseCombinationFloat(~toPointSetFn, ~algebraicCombination=#Logarithm, ~f)
+ ->E.R2.fmap(r => Dist(r))
+ ->OutputLocal.fromResult
+ | ToDist(Scale(#Power, f)) =>
+ dist
+ ->GenericDist.pointwiseCombinationFloat(~toPointSetFn, ~algebraicCombination=#Power, ~f)
+ ->E.R2.fmap(r => Dist(r))
+ ->OutputLocal.fromResult
| ToDistCombination(Algebraic(_), _, #Float(_)) => GenDistError(NotYetImplemented)
| ToDistCombination(Algebraic(strategy), arithmeticOperation, #Dist(t2)) =>
dist
@@ -189,6 +199,12 @@ let rec run = (~env, functionCallInfo: functionCallInfo): outputType => {
->GenericDist.mixture(~scaleMultiplyFn=scaleMultiply, ~pointwiseAddFn=pointwiseAdd)
->E.R2.fmap(r => Dist(r))
->OutputLocal.fromResult
+ | FromSamples(xs) =>
+ xs
+ ->SampleSetDist.make
+ ->E.R2.errMap(x => DistributionTypes.SampleSetError(x))
+ ->E.R2.fmap(x => x->DistributionTypes.SampleSet->Dist)
+ ->OutputLocal.fromResult
}
}
@@ -229,6 +245,7 @@ module Constructors = {
let isNormalized = (~env, dist) => C.isNormalized(dist)->run(~env)->toBoolR
let toPointSet = (~env, dist) => C.toPointSet(dist)->run(~env)->toDistR
let toSampleSet = (~env, dist, n) => C.toSampleSet(dist, n)->run(~env)->toDistR
+ let fromSamples = (~env, xs) => C.fromSamples(xs)->run(~env)->toDistR
let truncate = (~env, dist, leftCutoff, rightCutoff) =>
C.truncate(dist, leftCutoff, rightCutoff)->run(~env)->toDistR
let inspect = (~env, dist) => C.inspect(dist)->run(~env)->toDistR
diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi
index 5ad34354..fcaeb5e4 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi
+++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionOperation/DistributionOperation.resi
@@ -61,6 +61,8 @@ module Constructors: {
@genType
let toSampleSet: (~env: env, genericDist, int) => result
@genType
+ let fromSamples: (~env: env, SampleSetDist.t) => result
+ @genType
let truncate: (~env: env, genericDist, option, option) => result
@genType
let inspect: (~env: env, genericDist) => result
diff --git a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res
index 93f86798..0d413bf4 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/DistributionTypes.res
@@ -11,7 +11,7 @@ type error =
| NotYetImplemented
| Unreachable
| DistributionVerticalShiftIsInvalid
- | TooFewSamples
+ | SampleSetError(SampleSetDist.sampleSetError)
| ArgumentError(string)
| OperationError(Operation.Error.t)
| PointSetConversionError(SampleSetDist.pointsetConversionError)
@@ -35,7 +35,8 @@ module Error = {
| DistributionVerticalShiftIsInvalid => "Distribution Vertical Shift is Invalid"
| ArgumentError(s) => `Argument Error ${s}`
| LogarithmOfDistributionError(s) => `Logarithm of input error: ${s}`
- | TooFewSamples => "Too Few Samples"
+ | SampleSetError(TooFewSamples) => "Too Few Samples"
+ | SampleSetError(NonNumericInput(err)) => `Found a non-number in input: ${err}`
| OperationError(err) => Operation.Error.toString(err)
| PointSetConversionError(err) => SampleSetDist.pointsetConversionErrorToString(err)
| SparklineError(err) => PointSetTypes.sparklineErrorToString(err)
@@ -47,10 +48,7 @@ module Error = {
let resultStringToResultError: result<'a, string> => result<'a, error> = n =>
n->E.R2.errMap(r => r->fromString)
- let sampleErrorToDistErr = (err: SampleSetDist.sampleSetError): error =>
- switch err {
- | TooFewSamples => TooFewSamples
- }
+ let sampleErrorToDistErr = (err: SampleSetDist.sampleSetError): error => SampleSetError(err)
}
@genType
@@ -68,12 +66,19 @@ module DistributionOperation = {
| #Pdf(float)
| #Mean
| #Sample
+ | #IntegralSum
+ ]
+
+ type toScaleFn = [
+ | #Power
+ | #Logarithm
]
type toDist =
| Normalize
| ToPointSet
| ToSampleSet(int)
+ | Scale(toScaleFn, float)
| Truncate(option, option)
| Inspect
@@ -99,6 +104,7 @@ module DistributionOperation = {
type genericFunctionCallInfo =
| FromDist(fromDist, genericDist)
| FromFloat(fromDist, float)
+ | FromSamples(array)
| Mixture(array<(genericDist, float)>)
let distCallToString = (distFunction: fromDist): string =>
@@ -113,6 +119,8 @@ module DistributionOperation = {
| ToDist(ToSampleSet(r)) => `toSampleSet(${E.I.toString(r)})`
| ToDist(Truncate(_, _)) => `truncate`
| ToDist(Inspect) => `inspect`
+ | ToDist(Scale(#Power, r)) => `scalePower(${E.Float.toFixed(r)})`
+ | ToDist(Scale(#Logarithm, r)) => `scaleLog(${E.Float.toFixed(r)})`
| ToString(ToString) => `toString`
| ToString(ToSparkline(n)) => `toSparkline(${E.I.toString(n)})`
| ToBool(IsNormalized) => `isNormalized`
@@ -124,6 +132,7 @@ module DistributionOperation = {
switch d {
| FromDist(f, _) | FromFloat(f, _) => distCallToString(f)
| Mixture(_) => `mixture`
+ | FromSamples(_) => `fromSamples`
}
}
module Constructors = {
@@ -140,8 +149,11 @@ module Constructors = {
let isNormalized = (dist): t => FromDist(ToBool(IsNormalized), dist)
let toPointSet = (dist): t => FromDist(ToDist(ToPointSet), dist)
let toSampleSet = (dist, r): t => FromDist(ToDist(ToSampleSet(r)), dist)
+ let fromSamples = (xs): t => FromSamples(xs)
let truncate = (dist, left, right): t => FromDist(ToDist(Truncate(left, right)), dist)
let inspect = (dist): t => FromDist(ToDist(Inspect), dist)
+ let scalePower = (dist, n): t => FromDist(ToDist(Scale(#Power, n)), dist)
+ let scaleLogarithm = (dist, n): t => FromDist(ToDist(Scale(#Logarithm, n)), dist)
let toString = (dist): t => FromDist(ToString(ToString), dist)
let toSparkline = (dist, n): t => FromDist(ToString(ToSparkline(n)), dist)
let algebraicAdd = (dist1, dist2: genericDist): t => FromDist(
diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res
index c19bdf7f..160ce640 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.res
@@ -62,26 +62,31 @@ let isNormalized = (t: t): bool => Js.Math.abs_float(integralEndY(t) -. 1.0) < 1
let toFloatOperation = (
t,
~toPointSetFn: toPointSetFn,
- ~distToFloatOperation: Operation.distToFloatOperation,
+ ~distToFloatOperation: DistributionTypes.DistributionOperation.toFloat,
) => {
- let trySymbolicSolution = switch (t: t) {
- | Symbolic(r) => SymbolicDist.T.operate(distToFloatOperation, r)->E.R.toOption
- | _ => None
- }
+ switch distToFloatOperation {
+ | #IntegralSum => Ok(integralEndY(t))
+ | (#Pdf(_) | #Cdf(_) | #Inv(_) | #Mean | #Sample) as op => {
+ let trySymbolicSolution = switch (t: t) {
+ | Symbolic(r) => SymbolicDist.T.operate(op, r)->E.R.toOption
+ | _ => None
+ }
- let trySampleSetSolution = switch ((t: t), distToFloatOperation) {
- | (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some
- | (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some
- | (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some
- | _ => None
- }
+ let trySampleSetSolution = switch ((t: t), distToFloatOperation) {
+ | (SampleSet(sampleSet), #Mean) => SampleSetDist.mean(sampleSet)->Some
+ | (SampleSet(sampleSet), #Sample) => SampleSetDist.sample(sampleSet)->Some
+ | (SampleSet(sampleSet), #Inv(r)) => SampleSetDist.percentile(sampleSet, r)->Some
+ | _ => None
+ }
- switch trySymbolicSolution {
- | Some(r) => Ok(r)
- | None =>
- switch trySampleSetSolution {
- | Some(r) => Ok(r)
- | None => toPointSetFn(t)->E.R2.fmap(PointSetDist.operate(distToFloatOperation))
+ switch trySymbolicSolution {
+ | Some(r) => Ok(r)
+ | None =>
+ switch trySampleSetSolution {
+ | Some(r) => Ok(r)
+ | None => toPointSetFn(t)->E.R2.fmap(PointSetDist.operate(op))
+ }
+ }
}
}
}
diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi
index e91803e2..3d143edc 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi
+++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi
@@ -20,7 +20,7 @@ let isNormalized: t => bool
let toFloatOperation: (
t,
~toPointSetFn: toPointSetFn,
- ~distToFloatOperation: Operation.distToFloatOperation,
+ ~distToFloatOperation: DistributionTypes.DistributionOperation.toFloat,
) => result
@genType
diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res
index d4286387..105b5a05 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Continuous.res
@@ -156,8 +156,10 @@ let reduce = (
~integralSumCachesFn: (float, float) => option=(_, _) => None,
fn: (float, float) => result,
continuousShapes,
-): result =>
- continuousShapes |> E.A.R.foldM(combinePointwise(~integralSumCachesFn, fn), empty)
+): result => {
+ let merge = combinePointwise(~integralSumCachesFn, fn)
+ continuousShapes |> E.A.R.foldM(merge, empty)
+}
let mapYResult = (
~integralSumCacheFn=_ => None,
diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res
index fdc921c6..1149df7e 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res
@@ -34,9 +34,10 @@ let lastY = (t: t) => t |> getShape |> XYShape.T.lastY
let combinePointwise = (
~integralSumCachesFn=(_, _) => None,
+ fn,
t1: PointSetTypes.discreteShape,
t2: PointSetTypes.discreteShape,
-): PointSetTypes.discreteShape => {
+): result => {
let combinedIntegralSum = Common.combineIntegralSums(
integralSumCachesFn,
t1.integralSumCache,
@@ -49,16 +50,22 @@ let combinePointwise = (
make(
~integralSumCache=combinedIntegralSum,
XYShape.PointwiseCombination.combine(
- (a, b) => Ok(a +. b),
+ fn,
XYShape.XtoY.discreteInterpolator,
t1.xyShape,
t2.xyShape,
)->E.R.toExn("Addition operation should never fail", _),
- )
+ )->Ok
}
-let reduce = (~integralSumCachesFn=(_, _) => None, discreteShapes): PointSetTypes.discreteShape =>
- discreteShapes |> E.A.fold_left(combinePointwise(~integralSumCachesFn), empty)
+let reduce = (
+ ~integralSumCachesFn=(_, _) => None,
+ fn: (float, float) => result,
+ discreteShapes: array,
+): result => {
+ let merge = combinePointwise(~integralSumCachesFn, fn)
+ discreteShapes |> E.A.R.foldM(merge, empty)
+}
let updateIntegralSumCache = (integralSumCache, t: t): t => {
...t,
diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Mixed.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Mixed.res
index 4ce2bdd6..98e7923a 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Mixed.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Mixed.res
@@ -316,7 +316,10 @@ let combinePointwise = (
t2: t,
): result => {
let reducedDiscrete =
- [t1, t2] |> E.A.fmap(toDiscrete) |> E.A.O.concatSomes |> Discrete.reduce(~integralSumCachesFn)
+ [t1, t2]
+ |> E.A.fmap(toDiscrete)
+ |> E.A.O.concatSomes
+ |> Discrete.reduce(~integralSumCachesFn, fn)
let reducedContinuous =
[t1, t2]
@@ -335,11 +338,11 @@ let combinePointwise = (
t1.integralCache,
t2.integralCache,
)
- reducedContinuous->E.R2.fmap(continuous =>
+ E.R.merge(reducedContinuous, reducedDiscrete)->E.R2.fmap(((continuous, discrete)) =>
make(
~integralSumCache=combinedIntegralSum,
~integralCache=combinedIntegral,
- ~discrete=reducedDiscrete,
+ ~discrete,
~continuous,
)
)
diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res
index 12aa5477..00c900dc 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetDist.res
@@ -84,7 +84,12 @@ let combinePointwise = (
m2,
)->E.R2.fmap(x => PointSetTypes.Continuous(x))
| (Discrete(m1), Discrete(m2)) =>
- Ok(PointSetTypes.Discrete(Discrete.combinePointwise(~integralSumCachesFn, m1, m2)))
+ Discrete.combinePointwise(
+ ~integralSumCachesFn,
+ fn,
+ m1,
+ m2,
+ )->E.R2.fmap(x => PointSetTypes.Discrete(x))
| (m1, m2) =>
Mixed.combinePointwise(
~integralSumCachesFn,
diff --git a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist.res b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist.res
index 14c66812..55b334c5 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist.res
@@ -1,11 +1,12 @@
@genType
module Error = {
@genType
- type sampleSetError = TooFewSamples
+ type sampleSetError = TooFewSamples | NonNumericInput(string)
let sampleSetErrorToString = (err: sampleSetError): string =>
switch err {
| TooFewSamples => "Too few samples when constructing sample set"
+ | NonNumericInput(err) => `Found a non-number in input: ${err}`
}
@genType
diff --git a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist_Bandwidth.res b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist_Bandwidth.res
index aef659d1..29d48ad3 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist_Bandwidth.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/SampleSetDist/SampleSetDist_Bandwidth.res
@@ -1,27 +1,30 @@
//The math here was taken from https://github.com/jasondavies/science.js/blob/master/src/stats/SampleSetDist_Bandwidth.js
-
+let {iqr_percentile, nrd0_lo_denominator, one, nrd0_coef, nrd_coef, nrd_fractionalPower} = module(
+ MagicNumbers.SampleSetBandwidth
+)
let len = x => E.A.length(x) |> float_of_int
-let iqr = x => Jstat.percentile(x, 0.75, true) -. Jstat.percentile(x, 0.25, true)
+let iqr = x =>
+ Jstat.percentile(x, iqr_percentile, true) -. Jstat.percentile(x, 1.0 -. iqr_percentile, true)
// Silverman, B. W. (1986) Density Estimation. London: Chapman and Hall.
let nrd0 = x => {
let hi = Js_math.sqrt(Jstat.variance(x))
- let lo = Js_math.minMany_float([hi, iqr(x) /. 1.34])
+ let lo = Js_math.minMany_float([hi, iqr(x) /. nrd0_lo_denominator])
let e = Js_math.abs_float(x[1])
let lo' = switch (lo, hi, e) {
| (lo, _, _) if !Js.Float.isNaN(lo) => lo
| (_, hi, _) if !Js.Float.isNaN(hi) => hi
| (_, _, e) if !Js.Float.isNaN(e) => e
- | _ => 1.0
+ | _ => one
}
- 0.9 *. lo' *. Js.Math.pow_float(~base=len(x), ~exp=-0.2)
+ nrd0_coef *. lo' *. Js.Math.pow_float(~base=len(x), ~exp=nrd_fractionalPower)
}
// Scott, D. W. (1992) Multivariate Density Estimation: Theory, Practice, and Visualization. Wiley.
let nrd = x => {
- let h = iqr(x) /. 1.34
- 1.06 *.
+ let h = iqr(x) /. nrd0_lo_denominator
+ nrd_coef *.
Js.Math.min_float(Js.Math.sqrt(Jstat.variance(x)), h) *.
- Js.Math.pow_float(~base=len(x), ~exp=-1.0 /. 5.0)
+ Js.Math.pow_float(~base=len(x), ~exp=nrd_fractionalPower)
}
diff --git a/packages/squiggle-lang/src/rescript/MagicNumbers.res b/packages/squiggle-lang/src/rescript/MagicNumbers.res
index 124a44f4..0f059c03 100644
--- a/packages/squiggle-lang/src/rescript/MagicNumbers.res
+++ b/packages/squiggle-lang/src/rescript/MagicNumbers.res
@@ -35,3 +35,16 @@ module ToPointSet = {
*/
let minDiscreteToKeep = samples => max(20, E.A.length(samples) / 50)
}
+
+module SampleSetBandwidth = {
+ // Silverman, B. W. (1986) Density Estimation. London: Chapman and Hall.
+ // Scott, D. W. (1992) Multivariate Density Estimation: Theory, Practice, and Visualization. Wiley.
+ let iqr_percentile = 0.75
+ let iqr_percentile_complement = 1.0 -. iqr_percentile
+ let nrd0_lo_denominator = 1.34
+ let one = 1.0
+ let nrd0_coef = 0.9
+
+ let nrd_coef = 1.06
+ let nrd_fractionalPower = -0.2
+}
diff --git a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res
index 0bfd3cba..17498612 100644
--- a/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res
+++ b/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res
@@ -130,6 +130,7 @@ module Helpers = {
| Error(err) => GenDistError(ArgumentError(err))
}
}
+ | Some(EvNumber(_))
| Some(EvDistribution(_)) =>
switch parseDistributionArray(args) {
| Ok(distributions) => mixtureWithDefaultWeights(distributions)
@@ -194,6 +195,7 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall, _environment)
->SymbolicConstructors.symbolicResultToOutput
| ("sample", [EvDistribution(dist)]) => Helpers.toFloatFn(#Sample, dist)
| ("mean", [EvDistribution(dist)]) => Helpers.toFloatFn(#Mean, dist)
+ | ("integralSum", [EvDistribution(dist)]) => Helpers.toFloatFn(#IntegralSum, dist)
| ("toString", [EvDistribution(dist)]) => Helpers.toStringFn(ToString, dist)
| ("toSparkline", [EvDistribution(dist)]) => Helpers.toStringFn(ToSparkline(20), dist)
| ("toSparkline", [EvDistribution(dist), EvNumber(n)]) =>
@@ -209,6 +211,15 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall, _environment)
| ("normalize", [EvDistribution(dist)]) => Helpers.toDistFn(Normalize, dist)
| ("isNormalized", [EvDistribution(dist)]) => Helpers.toBoolFn(IsNormalized, dist)
| ("toPointSet", [EvDistribution(dist)]) => Helpers.toDistFn(ToPointSet, dist)
+ | ("scaleLog", [EvDistribution(dist)]) =>
+ Helpers.toDistFn(Scale(#Logarithm, MagicNumbers.Math.e), dist)
+ | ("scaleLog10", [EvDistribution(dist)]) => Helpers.toDistFn(Scale(#Logarithm, 10.0), dist)
+ | ("scaleLog", [EvDistribution(dist), EvNumber(float)]) =>
+ Helpers.toDistFn(Scale(#Logarithm, float), dist)
+ | ("scalePow", [EvDistribution(dist), EvNumber(float)]) =>
+ Helpers.toDistFn(Scale(#Power, float), dist)
+ | ("scaleExp", [EvDistribution(dist)]) =>
+ Helpers.toDistFn(Scale(#Power, MagicNumbers.Math.e), dist)
| ("cdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Cdf(float), dist)
| ("pdf", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Pdf(float), dist)
| ("inv", [EvDistribution(dist), EvNumber(float)]) => Helpers.toFloatFn(#Inv(float), dist)
@@ -216,6 +227,14 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall, _environment)
Helpers.toDistFn(ToSampleSet(Belt.Int.fromFloat(float)), dist)
| ("toSampleSet", [EvDistribution(dist)]) =>
Helpers.toDistFn(ToSampleSet(MagicNumbers.Environment.defaultSampleCount), dist)
+ | ("fromSamples", [EvArray(inputArray)]) => {
+ let _wrapInputErrors = x => SampleSetDist.NonNumericInput(x)
+ let parsedArray = Helpers.parseNumberArray(inputArray)->E.R2.errMap(_wrapInputErrors)
+ switch parsedArray {
+ | Ok(array) => runGenericOperation(FromSamples(array))
+ | Error(e) => GenDistError(SampleSetError(e))
+ }->Some
+ }
| ("inspect", [EvDistribution(dist)]) => Helpers.toDistFn(Inspect, dist)
| ("truncateLeft", [EvDistribution(dist), EvNumber(float)]) =>
Helpers.toDistFn(Truncate(Some(float), None), dist)
diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res
index e0bcaf5c..472c32f7 100644
--- a/packages/squiggle-lang/src/rescript/Utility/E.res
+++ b/packages/squiggle-lang/src/rescript/Utility/E.res
@@ -289,6 +289,13 @@ module R = {
| Ok(r) => r->Ok
| Error(x) => x->f->Error
}
+
+ //I'm not sure what to call this.
+ let unify = (a: result<'a, 'b>, c: 'b => 'a): 'a =>
+ switch a {
+ | Ok(x) => x
+ | Error(x) => c(x)
+ }
}
module R2 = {
@@ -307,6 +314,8 @@ module R2 = {
| Ok(x) => x->Ok
| Error(x) => x->f->Error
}
+
+ let toExn = (a, b) => R.toExn(b, a)
}
let safe_fn_of_string = (fn, s: string): option<'a> =>
@@ -350,7 +359,7 @@ module JsDate = {
/* List */
module L = {
module Util = {
- let eq = (a, b) => a == b
+ let eq = \"=="
}
let fmap = List.map
let get = Belt.List.get
diff --git a/packages/website/docs/Features/Functions.mdx b/packages/website/docs/Features/Functions.mdx
index e37ea315..1de7514b 100644
--- a/packages/website/docs/Features/Functions.mdx
+++ b/packages/website/docs/Features/Functions.mdx
@@ -98,6 +98,19 @@ bound `a`, mode `b` and upper bound `c`.
Squiggle, when the context is right, automatically casts a float to a constant distribution.
+## `fromSamples`
+
+The last distribution constructor takes an array of samples and constructs a sample set distribution.
+
+
+
+#### Validity
+
+For `fromSamples(xs)`,
+
+- `xs.length > 5`
+- Strictly every element of `xs` must be a number.
+
## Operating on distributions
Here are the ways we combine distributions.
@@ -315,6 +328,16 @@ Or `PointSet` format
+### `toSampleSet` has two signatures
+
+Above, we saw the unary `toSampleSet`, which uses an internal hardcoded number of samples. If you'd like to provide the number of samples, it has a binary signature as well (floored)
+
+
+
+#### Validity
+
+- Second argument to `toSampleSet` must be a number.
+
## Normalization
Some distribution operations (like horizontal shift) return an unnormalized distriibution.
@@ -333,18 +356,6 @@ We provide a predicate `isNormalized`, for when we have simple control flow
- Input to `isNormalized` must be a dist
-## Convert any distribution to a sample set distribution
-
-`toSampleSet` has two signatures
-
-It is unary when you use an internal hardcoded number of samples
-
-
-
-And binary when you provide a number of samples (floored)
-
-
-
## `inspect`
You may like to debug by right clicking your browser and using the _inspect_ functionality on the webpage, and viewing the _console_ tab. Then, wrap your squiggle output with `inspect` to log an internal representation.
diff --git a/yarn.lock b/yarn.lock
index 3597fea6..89928253 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6498,7 +6498,7 @@ coa@^2.0.2:
chalk "^2.4.1"
q "^1.1.2"
-codecov@3.8.3:
+codecov@^3.8.3:
version "3.8.3"
resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.8.3.tgz#9c3e364b8a700c597346ae98418d09880a3fdbe7"
integrity sha512-Y8Hw+V3HgR7V71xWH2vQ9lyS358CbGCldWlJFR0JirqoGtOoas3R3/OclRTvgUYFK29mmJICDPauVKmpqbwhOA==
@@ -8607,7 +8607,7 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-fast-check@2.25.0, fast-check@^2.17.0:
+fast-check@^2.17.0, fast-check@^2.25.0:
version "2.25.0"
resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-2.25.0.tgz#5146601851bf3be0953bd17eb2b7d547936c6561"
integrity sha512-wRUT2KD2lAmT75WNIJIHECawoUUMHM0I5jrlLXGtGeqmPL8jl/EldUDjY1VCp6fDY8yflyfUeIOsOBrIbIiArg==
@@ -11627,7 +11627,7 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
-lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
+lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -11751,7 +11751,7 @@ markdown-to-jsx@^7.1.3:
resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz#a5f22102fb12241c8cea1ca6a4050bb76b23a25d"
integrity sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w==
-mathjs@10.5.0:
+mathjs@^10.5.0:
version "10.5.0"
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.5.0.tgz#f81d0518fe7b4b2a0b85e1125b8ecfc364fb0292"
integrity sha512-gRnSY9psN9zgiB2QV9F4XbuX5hwjxY5Ou7qoTFWDbn2vZ3UEs+sjfK/SRg2WP30TNfZWpwlGdp8H1knFJnpFdA==
@@ -12120,7 +12120,7 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-moduleserve@0.9.1:
+moduleserve@^0.9.1:
version "0.9.1"
resolved "https://registry.yarnpkg.com/moduleserve/-/moduleserve-0.9.1.tgz#11bad4337ea248d7eaf10d2c7f8649a8c3b9c1f8"
integrity sha512-WF2BeGnM2Ko7bdICgJO+Ibu+ZD33ExJHzOzTDsCUzfZnvnFfheEIYBTWyIqSRU0tXh4UTQ1krDOCglFTJPBMow==
@@ -14439,7 +14439,7 @@ react-ace@10.0.0:
lodash.isequal "^4.5.0"
prop-types "^15.7.2"
-react-ace@10.1.0:
+react-ace@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-10.1.0.tgz#d348eac2b16475231779070b6cd16768deed565f"
integrity sha512-VkvUjZNhdYTuKOKQpMIZi7uzZZVgzCjM7cLYu6F64V0mejY8a2XTyPUIMszC6A4trbeMIHbK5fYFcT/wkP/8VA==
@@ -14693,7 +14693,7 @@ react-router@6.3.0, react-router@^6.0.0:
dependencies:
history "^5.2.0"
-react-scripts@5.0.1:
+react-scripts@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.1.tgz#6285dbd65a8ba6e49ca8d651ce30645a6d980003"
integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==