Merge branch 'develop' into reducer-typecheck-example
This commit is contained in:
commit
1a5f8dee72
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@quri/squiggle-components",
|
||||
"version": "0.2.23",
|
||||
"version": "0.2.24",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom": "^0.7.2",
|
||||
|
|
|
@ -39,13 +39,10 @@ interface FunctionChart1NumberProps {
|
|||
type point = { x: number; value: result<number, string> };
|
||||
|
||||
let getFunctionImage = ({ chartSettings, fn, environment }) => {
|
||||
//We adjust the count, because the count is made for distributions, which are much more expensive to estimate
|
||||
let adjustedCount = chartSettings.count * 20;
|
||||
|
||||
let chartPointsToRender = _rangeByCount(
|
||||
chartSettings.start,
|
||||
chartSettings.stop,
|
||||
adjustedCount
|
||||
chartSettings.count
|
||||
);
|
||||
|
||||
let chartPointsData: point[] = chartPointsToRender.map((x) => {
|
||||
|
|
|
@ -73,7 +73,7 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = React.memo(
|
|||
expY = false,
|
||||
diagramStart = 0,
|
||||
diagramStop = 10,
|
||||
diagramCount = 100,
|
||||
diagramCount = 20,
|
||||
tickFormat,
|
||||
minX,
|
||||
maxX,
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import React from "react";
|
||||
import { SquiggleEditor } from "./SquiggleEditor";
|
||||
import type { SquiggleEditorProps } from "./SquiggleEditor";
|
||||
import { runPartial, defaultBindings } from "@quri/squiggle-lang";
|
||||
import type {
|
||||
result,
|
||||
errorValue,
|
||||
bindings as bindingsType,
|
||||
} from "@quri/squiggle-lang";
|
||||
|
||||
function resultDefault(x: result<bindingsType, errorValue>): bindingsType {
|
||||
switch (x.tag) {
|
||||
case "Ok":
|
||||
return x.value;
|
||||
case "Error":
|
||||
return defaultBindings;
|
||||
}
|
||||
}
|
||||
|
||||
export type SquiggleEditorWithImportedBindingsProps = SquiggleEditorProps & {
|
||||
bindingsImportUrl: string;
|
||||
};
|
||||
|
||||
export const SquiggleEditorWithImportedBindings: React.FC<
|
||||
SquiggleEditorWithImportedBindingsProps
|
||||
> = (props) => {
|
||||
const { bindingsImportUrl, ...editorProps } = props;
|
||||
const [bindingsResult, setBindingsResult] = React.useState({
|
||||
tag: "Ok",
|
||||
value: defaultBindings,
|
||||
} as result<bindingsType, errorValue>);
|
||||
React.useEffect(() => {
|
||||
async function retrieveBindings(fileName: string) {
|
||||
let contents = await fetch(fileName).then((response) => {
|
||||
return response.text();
|
||||
});
|
||||
setBindingsResult(
|
||||
runPartial(
|
||||
contents,
|
||||
editorProps.bindings,
|
||||
editorProps.environment,
|
||||
editorProps.jsImports
|
||||
)
|
||||
);
|
||||
}
|
||||
retrieveBindings(bindingsImportUrl);
|
||||
}, [bindingsImportUrl]);
|
||||
const deliveredBindings = resultDefault(bindingsResult);
|
||||
return (
|
||||
<SquiggleEditor {...{ ...editorProps, bindings: deliveredBindings }} />
|
||||
);
|
||||
};
|
|
@ -1,287 +0,0 @@
|
|||
import * as React from "react";
|
||||
import {
|
||||
squiggleExpression,
|
||||
environment,
|
||||
declaration,
|
||||
} from "@quri/squiggle-lang";
|
||||
import { NumberShower } from "./NumberShower";
|
||||
import {
|
||||
DistributionChart,
|
||||
DistributionPlottingSettings,
|
||||
} from "./DistributionChart";
|
||||
import { FunctionChart, FunctionChartSettings } from "./FunctionChart";
|
||||
|
||||
function getRange<a>(x: declaration<a>) {
|
||||
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<a>(x: declaration<a>): 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<VariableBoxProps> = ({
|
||||
heading = "Error",
|
||||
children,
|
||||
showTypes = false,
|
||||
}) => {
|
||||
if (showTypes) {
|
||||
return (
|
||||
<div className="bg-white border border-grey-200 m-2">
|
||||
<div className="border-b border-grey-200 p-3">
|
||||
<header className="font-mono">{heading}</header>
|
||||
</div>
|
||||
<div className="p-3">{children}</div>
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
};
|
||||
|
||||
export interface SquiggleItemProps {
|
||||
/** The input string for squiggle */
|
||||
expression: squiggleExpression;
|
||||
width?: number;
|
||||
height: number;
|
||||
distributionPlotSettings: DistributionPlottingSettings;
|
||||
/** Whether to show type information */
|
||||
showTypes: boolean;
|
||||
/** Settings for displaying functions */
|
||||
chartSettings: FunctionChartSettings;
|
||||
/** Environment for further function executions */
|
||||
environment: environment;
|
||||
}
|
||||
|
||||
export const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||
expression,
|
||||
width,
|
||||
height,
|
||||
distributionPlotSettings,
|
||||
showTypes = false,
|
||||
chartSettings,
|
||||
environment,
|
||||
}) => {
|
||||
switch (expression.tag) {
|
||||
case "number":
|
||||
return (
|
||||
<VariableBox heading="Number" showTypes={showTypes}>
|
||||
<div className="font-semibold text-slate-600">
|
||||
<NumberShower precision={3} number={expression.value} />
|
||||
</div>
|
||||
</VariableBox>
|
||||
);
|
||||
case "distribution": {
|
||||
const distType = expression.value.type();
|
||||
return (
|
||||
<VariableBox
|
||||
heading={`Distribution (${distType})`}
|
||||
showTypes={showTypes}
|
||||
>
|
||||
{distType === "Symbolic" && showTypes ? (
|
||||
<div>{expression.value.toString()}</div>
|
||||
) : null}
|
||||
<DistributionChart
|
||||
distribution={expression.value}
|
||||
{...distributionPlotSettings}
|
||||
height={height}
|
||||
width={width}
|
||||
/>
|
||||
</VariableBox>
|
||||
);
|
||||
}
|
||||
case "string":
|
||||
return (
|
||||
<VariableBox heading="String" showTypes={showTypes}>
|
||||
<span className="text-slate-400">"</span>
|
||||
<span className="text-slate-600 font-semibold">
|
||||
{expression.value}
|
||||
</span>
|
||||
<span className="text-slate-400">"</span>
|
||||
</VariableBox>
|
||||
);
|
||||
case "boolean":
|
||||
return (
|
||||
<VariableBox heading="Boolean" showTypes={showTypes}>
|
||||
{expression.value.toString()}
|
||||
</VariableBox>
|
||||
);
|
||||
case "symbol":
|
||||
return (
|
||||
<VariableBox heading="Symbol" showTypes={showTypes}>
|
||||
<span className="text-slate-500 mr-2">Undefined Symbol:</span>
|
||||
<span className="text-slate-600">{expression.value}</span>
|
||||
</VariableBox>
|
||||
);
|
||||
case "call":
|
||||
return (
|
||||
<VariableBox heading="Call" showTypes={showTypes}>
|
||||
{expression.value}
|
||||
</VariableBox>
|
||||
);
|
||||
case "array":
|
||||
return (
|
||||
<VariableBox heading="Array" showTypes={showTypes}>
|
||||
{expression.value.map((r, i) => (
|
||||
<div key={i} className="flex pt-1">
|
||||
<div className="flex-none bg-slate-100 rounded-sm px-1">
|
||||
<header className="text-slate-400 font-mono">{i}</header>
|
||||
</div>
|
||||
<div className="px-2 mb-2 grow">
|
||||
<SquiggleItem
|
||||
key={i}
|
||||
expression={r}
|
||||
width={width !== undefined ? width - 20 : width}
|
||||
height={50}
|
||||
distributionPlotSettings={distributionPlotSettings}
|
||||
showTypes={showTypes}
|
||||
chartSettings={chartSettings}
|
||||
environment={environment}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</VariableBox>
|
||||
);
|
||||
case "record":
|
||||
return (
|
||||
<VariableBox heading="Record" showTypes={showTypes}>
|
||||
<div className="space-y-3">
|
||||
{Object.entries(expression.value).map(([key, r]) => (
|
||||
<div key={key} className="flex space-x-2">
|
||||
<div className="flex-none">
|
||||
<header className="text-slate-500 font-mono">{key}:</header>
|
||||
</div>
|
||||
<div className="px-2 grow bg-gray-50 border border-gray-100 rounded-sm">
|
||||
<SquiggleItem
|
||||
expression={r}
|
||||
width={width !== undefined ? width - 20 : width}
|
||||
height={height / 3}
|
||||
showTypes={showTypes}
|
||||
distributionPlotSettings={distributionPlotSettings}
|
||||
chartSettings={chartSettings}
|
||||
environment={environment}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</VariableBox>
|
||||
);
|
||||
case "arraystring":
|
||||
return (
|
||||
<VariableBox heading="Array String" showTypes={showTypes}>
|
||||
{expression.value.map((r) => `"${r}"`).join(", ")}
|
||||
</VariableBox>
|
||||
);
|
||||
case "date":
|
||||
return (
|
||||
<VariableBox heading="Date" showTypes={showTypes}>
|
||||
{expression.value.toDateString()}
|
||||
</VariableBox>
|
||||
);
|
||||
case "void":
|
||||
return (
|
||||
<VariableBox heading="Void" showTypes={showTypes}>
|
||||
{"Void"}
|
||||
</VariableBox>
|
||||
);
|
||||
case "timeDuration": {
|
||||
return (
|
||||
<VariableBox heading="Time Duration" showTypes={showTypes}>
|
||||
<NumberShower precision={3} number={expression.value} />
|
||||
</VariableBox>
|
||||
);
|
||||
}
|
||||
case "lambda":
|
||||
return (
|
||||
<VariableBox heading="Function" showTypes={showTypes}>
|
||||
<div className="text-amber-700 bg-amber-100 rounded-md font-mono p-1 pl-2 mb-3 mt-1 text-sm">{`function(${expression.value.parameters.join(
|
||||
","
|
||||
)})`}</div>
|
||||
<FunctionChart
|
||||
fn={expression.value}
|
||||
chartSettings={chartSettings}
|
||||
distributionPlotSettings={distributionPlotSettings}
|
||||
height={height}
|
||||
environment={{
|
||||
sampleCount: environment.sampleCount / 10,
|
||||
xyPointLength: environment.xyPointLength / 10,
|
||||
}}
|
||||
/>
|
||||
</VariableBox>
|
||||
);
|
||||
case "lambdaDeclaration": {
|
||||
return (
|
||||
<VariableBox heading="Function Declaration" showTypes={showTypes}>
|
||||
<FunctionChart
|
||||
fn={expression.value.fn}
|
||||
chartSettings={getChartSettings(expression.value)}
|
||||
distributionPlotSettings={distributionPlotSettings}
|
||||
height={height}
|
||||
environment={{
|
||||
sampleCount: environment.sampleCount / 10,
|
||||
xyPointLength: environment.xyPointLength / 10,
|
||||
}}
|
||||
/>
|
||||
</VariableBox>
|
||||
);
|
||||
}
|
||||
case "module": {
|
||||
return (
|
||||
<VariableBox heading="Module" showTypes={showTypes}>
|
||||
<div className="space-y-3">
|
||||
{Object.entries(expression.value)
|
||||
.filter(([key, r]) => key !== "Math")
|
||||
.map(([key, r]) => (
|
||||
<div key={key} className="flex space-x-2">
|
||||
<div className="flex-none">
|
||||
<header className="text-slate-500 font-mono">{key}:</header>
|
||||
</div>
|
||||
<div className="px-2 grow bg-gray-50 border border-gray-100 rounded-sm">
|
||||
<SquiggleItem
|
||||
expression={r}
|
||||
width={width !== undefined ? width - 20 : width}
|
||||
height={height / 3}
|
||||
showTypes={showTypes}
|
||||
distributionPlotSettings={distributionPlotSettings}
|
||||
chartSettings={chartSettings}
|
||||
environment={environment}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</VariableBox>
|
||||
);
|
||||
}
|
||||
default: {
|
||||
return (
|
||||
<div>
|
||||
<span>No display for type: </span>{" "}
|
||||
<span className="font-semibold text-slate-600">{expression.tag}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -13,6 +13,7 @@ import { yupResolver } from "@hookform/resolvers/yup";
|
|||
import {
|
||||
ChartSquareBarIcon,
|
||||
CheckCircleIcon,
|
||||
ClipboardCopyIcon,
|
||||
CodeIcon,
|
||||
CogIcon,
|
||||
CurrencyDollarIcon,
|
||||
|
@ -40,6 +41,7 @@ import {
|
|||
defaultColor,
|
||||
defaultTickFormat,
|
||||
} from "../lib/distributionSpecBuilder";
|
||||
import { Button } from "./ui/Button";
|
||||
|
||||
type PlaygroundProps = SquiggleChartProps & {
|
||||
/** The initial squiggle string to put in the playground */
|
||||
|
@ -49,6 +51,8 @@ type PlaygroundProps = SquiggleChartProps & {
|
|||
onSettingsChange?(settings: any): void;
|
||||
/** Should we show the editor? */
|
||||
showEditor?: boolean;
|
||||
/** Useful for playground on squiggle website, where we update the anchor link based on current code and settings */
|
||||
showShareButton?: boolean;
|
||||
};
|
||||
|
||||
const schema = yup
|
||||
|
@ -197,6 +201,29 @@ const RunControls: React.FC<{
|
|||
);
|
||||
};
|
||||
|
||||
const ShareButton: React.FC = () => {
|
||||
const [isCopied, setIsCopied] = useState(false);
|
||||
const copy = () => {
|
||||
navigator.clipboard.writeText((window.top || window).location.href);
|
||||
setIsCopied(true);
|
||||
setTimeout(() => setIsCopied(false), 1000);
|
||||
};
|
||||
return (
|
||||
<div className="w-36">
|
||||
<Button onClick={copy} wide>
|
||||
{isCopied ? (
|
||||
"Copied to clipboard!"
|
||||
) : (
|
||||
<div className="flex items-center space-x-1">
|
||||
<ClipboardCopyIcon className="w-4 h-4" />
|
||||
<span>Copy share link</span>
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type PlaygroundContextShape = {
|
||||
getLeftPanelElement: () => HTMLDivElement | undefined;
|
||||
};
|
||||
|
@ -220,6 +247,7 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
|||
onCodeChange,
|
||||
onSettingsChange,
|
||||
showEditor = true,
|
||||
showShareButton = false,
|
||||
}) => {
|
||||
const [code, setCode] = useMaybeControlledValue({
|
||||
value: controlledCode,
|
||||
|
@ -370,13 +398,16 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
|||
<StyledTab name="View Settings" icon={ChartSquareBarIcon} />
|
||||
<StyledTab name="Input Variables" icon={CurrencyDollarIcon} />
|
||||
</StyledTab.List>
|
||||
<RunControls
|
||||
autorunMode={autorunMode}
|
||||
isStale={renderedCode !== code}
|
||||
run={run}
|
||||
isRunning={isRunning}
|
||||
onAutorunModeChange={setAutorunMode}
|
||||
/>
|
||||
<div className="flex space-x-2 items-center">
|
||||
<RunControls
|
||||
autorunMode={autorunMode}
|
||||
isStale={renderedCode !== code}
|
||||
run={run}
|
||||
isRunning={isRunning}
|
||||
onAutorunModeChange={setAutorunMode}
|
||||
/>
|
||||
{showShareButton && <ShareButton />}
|
||||
</div>
|
||||
</div>
|
||||
{vars.showEditor ? withEditor : withoutEditor}
|
||||
</div>
|
||||
|
|
22
packages/components/src/components/ui/Button.tsx
Normal file
22
packages/components/src/components/ui/Button.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
|
||||
type Props = {
|
||||
onClick: () => void;
|
||||
children: React.ReactNode;
|
||||
wide?: boolean; // stretch the button horizontally
|
||||
};
|
||||
|
||||
export const Button: React.FC<Props> = ({ onClick, wide, children }) => {
|
||||
return (
|
||||
<button
|
||||
className={clsx(
|
||||
"rounded-md py-1.5 px-2 bg-slate-500 text-white text-xs font-semibold flex items-center justify-center space-x-1",
|
||||
wide && "w-full"
|
||||
)}
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
|
@ -2,5 +2,6 @@ export { SquiggleChart } from "./components/SquiggleChart";
|
|||
export { SquiggleEditor, SquigglePartial } from "./components/SquiggleEditor";
|
||||
export { SquigglePlayground } from "./components/SquigglePlayground";
|
||||
export { SquiggleContainer } from "./components/SquiggleContainer";
|
||||
export { SquiggleEditorWithImportedBindings } from "./components/SquiggleEditorWithImportedBindings";
|
||||
|
||||
export { mergeBindings } from "@quri/squiggle-lang";
|
||||
|
|
|
@ -21,3 +21,16 @@ including sampling settings, in squiggle.
|
|||
{Template.bind({})}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="With share button"
|
||||
args={{
|
||||
defaultCode: "normal(5,2)",
|
||||
height: 800,
|
||||
showShareButton: true,
|
||||
}}
|
||||
>
|
||||
{Template.bind({})}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
|
|
@ -250,7 +250,7 @@ module T = Dist({
|
|||
|
||||
let downsample = (length, t): t =>
|
||||
t |> shapeMap(XYShape.XsConversion.proportionByProbabilityMass(length, integral(t).xyShape))
|
||||
let integralEndY = (t: t) => t.integralSumCache |> E.O.default(t |> integral |> lastY)
|
||||
let integralEndY = (t: t) => t.integralSumCache |> E.O.defaultFn(() => t |> integral |> lastY)
|
||||
let integralXtoY = (f, t: t) => t |> integral |> shapeFn(XYShape.XtoY.linear(f))
|
||||
let integralYtoX = (f, t: t) => t |> integral |> shapeFn(XYShape.YtoX.linear(f))
|
||||
let toContinuous = t => Some(t)
|
||||
|
|
|
@ -158,7 +158,8 @@ module T = Dist({
|
|||
Continuous.make(~interpolation=#Stepwise, integralShape)
|
||||
}
|
||||
|
||||
let integralEndY = (t: t) => t.integralSumCache |> E.O.default(t |> integral |> Continuous.lastY)
|
||||
let integralEndY = (t: t) =>
|
||||
t.integralSumCache |> E.O.defaultFn(() => t |> integral |> Continuous.lastY)
|
||||
let minX = shapeFn(XYShape.T.minX)
|
||||
let maxX = shapeFn(XYShape.T.maxX)
|
||||
let toDiscreteProbabilityMassFraction = _ => 1.0
|
||||
|
|
|
@ -13,9 +13,11 @@ let buildSimple = (
|
|||
~discrete: option<PointSetTypes.discreteShape>,
|
||||
): option<PointSetTypes.pointSetDist> => {
|
||||
let continuous =
|
||||
continuous |> E.O.default(Continuous.make(~integralSumCache=Some(0.0), {xs: [], ys: []}))
|
||||
continuous |> E.O.defaultFn(() =>
|
||||
Continuous.make(~integralSumCache=Some(0.0), {xs: [], ys: []})
|
||||
)
|
||||
let discrete =
|
||||
discrete |> E.O.default(Discrete.make(~integralSumCache=Some(0.0), {xs: [], ys: []}))
|
||||
discrete |> E.O.defaultFn(() => Discrete.make(~integralSumCache=Some(0.0), {xs: [], ys: []}))
|
||||
let cLength = continuous |> Continuous.getShape |> XYShape.T.xs |> E.A.length
|
||||
let dLength = discrete |> Discrete.getShape |> XYShape.T.xs |> E.A.length
|
||||
switch (cLength, dLength) {
|
||||
|
|
|
@ -16,7 +16,7 @@ let dispatch = (
|
|||
() => ReducerInterface_Duration.dispatch(call, environment),
|
||||
() => ReducerInterface_Number.dispatch(call, environment),
|
||||
() => FunctionRegistry_Library.dispatch(call, environment, reducer),
|
||||
])->E.O2.default(chain(call, environment, reducer))
|
||||
])->E.O2.defaultFn(() => chain(call, environment, reducer))
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -82,6 +82,11 @@ module O = {
|
|||
| None => d
|
||||
| Some(a) => a
|
||||
}
|
||||
let defaultFn = (d, o) =>
|
||||
switch o {
|
||||
| None => d()
|
||||
| Some(a) => a
|
||||
}
|
||||
let isSome = o =>
|
||||
switch o {
|
||||
| Some(_) => true
|
||||
|
@ -158,6 +163,7 @@ module O = {
|
|||
|
||||
module O2 = {
|
||||
let default = (a, b) => O.default(b, a)
|
||||
let defaultFn = (a, b) => O.defaultFn(b, a)
|
||||
let toExn = (a, b) => O.toExn(b, a)
|
||||
let fmap = (a, b) => O.fmap(b, a)
|
||||
let toResult = (a, b) => O.toResult(b, a)
|
||||
|
|
|
@ -9,7 +9,7 @@ Features:
|
|||
- Preview `.squiggle` files in a preview pane
|
||||
- Syntax highlighting for `.squiggle` and `.squiggleU` files
|
||||
|
||||
## Installation
|
||||
## Installation
|
||||
|
||||
You can install this extension by going to the "extensions" tab, searching for "Squiggle", and then installing it.
|
||||
|
||||
|
@ -23,7 +23,7 @@ After loading a `.squiggle` file, an "Open Preview" button will appear. If you c
|
|||
|
||||
### Configuration (optional)
|
||||
|
||||
Some preview settings, e.g. whether to show the summary table or types of outputs, can be configurable on in the VS Code settings and persist between different preview sessions. The VS Code settings can be accessed with the shortcut `Ctrl+,` with `Ctrl+Shift+P` + searching "Open Settings", or by accessing a file like `$HOME/.config/Code/User/settings.json` in Linux (see [here](https://stackoverflow.com/questions/65908987/how-can-i-open-visual-studio-codes-settings-json-file)) for other operating systems.
|
||||
Some preview settings, e.g. whether to show the summary table or types of outputs, can be configurable on in the VS Code settings and persist between different preview sessions. The VS Code settings can be accessed with the shortcut `Ctrl+,` with `Ctrl+Shift+P` + searching "Open Settings", or by accessing a file like `$HOME/.config/Code/User/settings.json` in Linux (see [here](https://stackoverflow.com/questions/65908987/how-can-i-open-visual-studio-codes-settings-json-file)) for other operating systems.
|
||||
|
||||
![](./images/vs-code-settings.png)
|
||||
|
||||
|
|
|
@ -7,7 +7,12 @@ import { SquiggleEditor } from "../../src/components/SquiggleEditor";
|
|||
|
||||
Much of the Squiggle math is imprecise. This can cause significant errors, so watch out.
|
||||
|
||||
Below are some specific examples to watch for. We'll work on improving these over time and adding much better warnings and error management.
|
||||
Below are a few specific examples to watch for. We'll work on improving these over time and adding much better warnings and error management.
|
||||
|
||||
## Operations on very small or large numbers, silently round to 0 and 1
|
||||
|
||||
Squiggle is poor at dealing with very small or large numbers, given fundamental limitations of floating point precision.
|
||||
See [this Github Issue](https://github.com/quantified-uncertainty/squiggle/issues/834).
|
||||
|
||||
## Mixtures of distributions with very different means
|
||||
|
||||
|
|
|
@ -3,26 +3,21 @@ title: Future Features
|
|||
sidebar_position: 3
|
||||
---
|
||||
|
||||
Squiggle is still very early. The main first goal is to become stable. This means having a clean codebase, having decent test coverage, and having a syntax we are reasonably confident in. Later on, there are many other features that will be interesting to explore.
|
||||
Squiggle is still very early. The main first goal is to become stable (to reach version 1.0). Right now we think it is useable to use for small projects, but do note that there are very likely some math bugs and performance problems.
|
||||
|
||||
## Programming Language Features
|
||||
|
||||
- Equality (a == b)
|
||||
- If/else statements
|
||||
- Arrays
|
||||
- Tables / Matrices
|
||||
- Simple objects
|
||||
- A simple type system
|
||||
- Simple module system (`Dist.Normal` instead of `normal`)
|
||||
- A simple time library & notation
|
||||
- Optional and default paramaters for functions
|
||||
- Anonymous Functions (This is particularly convenient in cases where tiny functions are submitted in forecasting competitions)
|
||||
- A notation to limit the domain of functions. For example, maybe a function only applies for t=[2 to 20]
|
||||
- Custom parser (Right now we're using Math.js's parser, which doesn't give us much flexibility)
|
||||
- "Partial-domain" distributions. For example, maybe someone has a distribution for when AGI will happen, but doesn't want to make any estimates past 2200.
|
||||
- Some story for tests
|
||||
- Much better code editor integration
|
||||
|
||||
## Distribution Features
|
||||
|
||||
There are many important distribution types that Squiggle doesn't yet support. Some key functions we'd like include:
|
||||
|
||||
[Metalog Distribution](https://en.wikipedia.org/wiki/Metalog_distribution)
|
||||
Add the Metalog distribution, and some convenient methods for generating these distributions. This might be a bit tricky because we might need or build a library to fit data. There's no Metalog javascript library yet, this would be pretty useful. There's already a Metalog library in Python, so that one could be used for inspiration.
|
||||
|
||||
|
@ -34,15 +29,6 @@ Takes a distribution and smoothens it. For example, [Elicit Forecast](https://fo
|
|||
**Probabilities**
|
||||
Right now Squiggle mostly works with probability distributions only, but it should also work smoothly with probabilities.
|
||||
|
||||
**Scoring**
|
||||
Have functions to score probabilities, probability distributions, and functions that return probability distributions.
|
||||
|
||||
**Full javascript library**
|
||||
A full Javascript library that accesses most of the probabilistic functionality of Squiggle, but can be used directly in javascript functions.
|
||||
|
||||
**Importance & quality scores**
|
||||
Workflows/functionality to declare the importance and coveredness of each part of the paramater space. For example, some subsets of the paramater space of a function might be much more important to get right than others. Similarly, the analyst might be much more certain about some parts than others. Ideally. they could decline sections.
|
||||
|
||||
**An interface to interpret & score Squiggle files**
|
||||
Squiggle functions need to be aggregated and scored. This should be done outside one Squiggle file. Maybe this should also be done in Squiggle, or maybe it should be done using Javascript.
|
||||
|
||||
|
@ -52,11 +38,8 @@ Of course, we'd also need good math for how the scoring should work, exactly.
|
|||
|
||||
This interface should also be able to handle changing Squiggle values. This is because people would be likely to want to update their functions over time, and that should be taken into account for scoring.
|
||||
|
||||
**Easily call other functions**
|
||||
It would be great to be able to call other people's Squiggle functions, from other Squiggle functions. This could raise a whole bunch of challenging issues. Additionally, it would be neat to call other data, both from knowledge graphs, and from regular APIs. Note that this could obviously complicate scoring a lot; I imagine that either easy scoring, or simple data fetching, would have to accept sacrifices.
|
||||
|
||||
**Correlated uncertainties**
|
||||
Right now there's no functionality to declare that two different distributions are correlated.
|
||||
**Importance & quality scores**
|
||||
Workflows/functionality to declare the importance and coveredness of each part of the paramater space. For example, some subsets of the paramater space of a function might be much more important to get right than others. Similarly, the analyst might be much more certain about some parts than others. Ideally. they could decline sections.
|
||||
|
||||
**Static / Sensitivity Analysis**
|
||||
Guesstimate has Sensitivity analysis that's pretty useful. This could be quite feasible to add, though it will likely require some thinking.
|
||||
|
@ -67,40 +50,5 @@ It might be useful to allow people to annotate functions and variables with long
|
|||
**Randomness Seeds**
|
||||
Right now, Monte Carlo simulations are totally random. It would be nicer to be able to enter a seed somehow in order to control the randomness. Or, with the same seed, the function should always return the same values. This would make debugging and similar easier.
|
||||
|
||||
## Major Standard Language Features
|
||||
|
||||
- Some testing story.
|
||||
- A custom code highlighting format.
|
||||
- Possibly a decent web GUI (a much more advanced playground).
|
||||
- A VS Code extention and similar.
|
||||
|
||||
## Bugs
|
||||
|
||||
- Discrete distributions are particularly buggy. Try `mm(1,2,3,4,5,6,7,8,9,10) .* (5 to 8)`
|
||||
|
||||
## New Functions
|
||||
|
||||
### Distributions
|
||||
|
||||
```js
|
||||
cauchy();
|
||||
pareto();
|
||||
metalog();
|
||||
```
|
||||
|
||||
Possibly change mm to mix, or mx(). Also, change input format, maybe to mx([a,b,c], [a,b,c]).
|
||||
|
||||
### Functions
|
||||
|
||||
```js
|
||||
samples(distribution, n);
|
||||
toPdf(distribution);
|
||||
toCdf(distribution);
|
||||
toHash(distribution);
|
||||
trunctate(distribution, leftValue, rightValue);
|
||||
leftTrunctate(distribution, leftValue);
|
||||
rightTrunctate(distribution, rightValue);
|
||||
distributionFromSamples(array, params);
|
||||
distributionFromPoints();
|
||||
distributionFromHash();
|
||||
```
|
||||
**Caching/Memoization**
|
||||
There are many performance improvements that Squiggle could have. We'll get to some of them eventually.
|
||||
|
|
|
@ -5,4 +5,5 @@ title: Gallery
|
|||
|
||||
- [Adjusting probabilities for the passage of time](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3/p/j8o6sgRerE3tqNWdj) by Nuño Sempere
|
||||
- [GiveWell's GiveDirectly cost effectiveness analysis](https://observablehq.com/@hazelfire/givewells-givedirectly-cost-effectiveness-analysis) by Sam Nolan
|
||||
- [List of QURI Squiggle Models](https://github.com/quantified-uncertainty/squiggle-models) by Nuño Sempere, Sam Nolan, and Ozzie Gooen
|
||||
- [Astronomical Waste](https://observablehq.com/@quinn-dougherty/waste)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Distribution Creation"
|
||||
title: "Distributions: Creation"
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
|
@ -17,7 +17,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.
|
||||
|
||||
<Tabs>
|
||||
<Tabs lazy>
|
||||
<TabItem value="ex1" label="5 to 10" default>
|
||||
When <code>5 to 10</code> is entered, both numbers are positive, so it
|
||||
generates a lognormal distribution with 5th and 95th percentiles at 5 and
|
||||
|
@ -35,8 +35,9 @@ If both values are above zero, a `lognormal` distribution is used. If not, a `no
|
|||
<SquiggleEditor defaultCode="-5 to -3" />
|
||||
</TabItem>
|
||||
<TabItem value="ex4" label="1 to 10000">
|
||||
It's very easy to generate distributions with very long tails. If this
|
||||
happens, you can click the "log x scale" box to view this using a log scale.
|
||||
It's very easy to generate distributions with very long tails. These can be
|
||||
impossible to see without changing view settings. (These settings are
|
||||
available in the Playground, but not this smaller editor component)
|
||||
<SquiggleEditor defaultCode="1 to 10000" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
@ -67,14 +68,14 @@ If both values are above zero, a `lognormal` distribution is used. If not, a `no
|
|||
|
||||
## Mixture
|
||||
|
||||
`mixture(...distributions: Distribution[], weights?: number[])`
|
||||
`mx(...distributions: Distribution[], weights?: number[])`
|
||||
`mixture(distributions: Distributions[], weights?: number[])`
|
||||
`mixture(...distributions: Distribution[], weights?: number[])`
|
||||
`mx(...distributions: Distribution[], weights?: number[])`
|
||||
`mixture(distributions: Distributions[], weights?: number[])`
|
||||
`mx(distributions: Distributions[], weights?: number[])`
|
||||
|
||||
The `mixture` mixes combines multiple distributions to create a mixture. You can optionally pass in a list of proportional weights.
|
||||
|
||||
<Tabs>
|
||||
<Tabs lazy>
|
||||
<TabItem value="ex1" label="Simple" default>
|
||||
<SquiggleEditor defaultCode="mixture(1 to 2, 5 to 8, 9 to 10)" />
|
||||
</TabItem>
|
||||
|
@ -110,6 +111,11 @@ The `mixture` mixes combines multiple distributions to create a mixture. You can
|
|||
<p>
|
||||
In this case, I have a 20% chance of spending 0 time with it. I might estimate my hours with,
|
||||
</p>
|
||||
<Admonition type="caution" title="Caution">
|
||||
<p>
|
||||
There's a temporary bug where the below render is compressed. If you toggle the code it will fix render correctly.
|
||||
</p>
|
||||
</Admonition>
|
||||
<SquiggleEditor
|
||||
defaultCode={`hours_the_project_will_take = 5 to 20
|
||||
chance_of_doing_anything = 0.8
|
||||
|
@ -139,12 +145,12 @@ mx(forecast, forecast_if_completely_wrong, [1-chance_completely_wrong, chance_co
|
|||
|
||||
Creates a [normal distribution](https://en.wikipedia.org/wiki/Normal_distribution) with the given mean and standard deviation.
|
||||
|
||||
<Tabs>
|
||||
<Tabs lazy>
|
||||
<TabItem value="ex1" label="normal(5,1)" default>
|
||||
<SquiggleEditor defaultCode="normal(5, 1)" />
|
||||
</TabItem>
|
||||
<TabItem value="ex2" label="normal(100000000000, 100000000000)">
|
||||
<SquiggleEditor defaultCode="normal(100000000000, 100000000000)" />
|
||||
<TabItem value="ex2" label="normal(1G, 1G)">
|
||||
<SquiggleEditor defaultCode="normal(1G, 1G)" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
@ -234,7 +240,7 @@ with values at 1 and 2. Therefore, this is the same as `mixture(pointMass(1),poi
|
|||
|
||||
`pointMass()` distributions are currently the only discrete distributions accessible in Squiggle.
|
||||
|
||||
<Tabs>
|
||||
<Tabs lazy>
|
||||
<TabItem value="ex1" label="pointMass(3)" default>
|
||||
<SquiggleEditor defaultCode="pointMass(3)" />
|
||||
</TabItem>
|
||||
|
@ -263,7 +269,7 @@ with values at 1 and 2. Therefore, this is the same as `mixture(pointMass(1),poi
|
|||
|
||||
Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) with the given `alpha` and `beta` values. For a good summary of the beta distribution, see [this explanation](https://stats.stackexchange.com/a/47782) on Stack Overflow.
|
||||
|
||||
<Tabs>
|
||||
<Tabs lazy>
|
||||
<TabItem value="ex1" label="beta(10, 20)" default>
|
||||
<SquiggleEditor defaultCode="beta(10,20)" />
|
||||
</TabItem>
|
||||
|
@ -279,11 +285,8 @@ Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) w
|
|||
<TabItem value="ex5" label="beta(0.8, 0.8)">
|
||||
<SquiggleEditor defaultCode="beta(0.8, 0.8)" />
|
||||
</TabItem>
|
||||
<TabItem
|
||||
value="from mean and standard deviation"
|
||||
label="beta({mean: 0.39, stdev: 0.1})"
|
||||
>
|
||||
<SquiggleEditor initialSquiggleString="beta({mean: 0.39, stdev: 0.1})" />
|
||||
<TabItem value="ex6" label="beta({mean: 0.39, stdev: 0.1})">
|
||||
<SquiggleEditor defaultCode="beta({mean: 0.39, stdev: 0.1})" />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
@ -300,7 +303,7 @@ Creates a [beta distribution](https://en.wikipedia.org/wiki/Beta_distribution) w
|
|||
</p>
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
<Tabs>
|
||||
<Tabs lazy>
|
||||
<TabItem value="ex1" label="beta(0.3, 0.3)" default>
|
||||
<SquiggleEditor defaultCode="beta(0.3, 0.3)" />
|
||||
</TabItem>
|
||||
|
@ -343,7 +346,7 @@ Creates a [triangular distribution](https://en.wikipedia.org/wiki/Triangular_dis
|
|||
|
||||
<SquiggleEditor defaultCode="triangular(1, 2, 4)" />
|
||||
|
||||
## FromList
|
||||
## SampleSet.fromList
|
||||
|
||||
`SampleSet.fromList(samples:number[])`
|
||||
|
||||
|
@ -367,3 +370,41 @@ Creates a sample set distribution using an array of samples.
|
|||
specificity.
|
||||
</p>
|
||||
</Admonition>
|
||||
|
||||
## PointSet.makeContinuous
|
||||
|
||||
`PointSet.makeContinuous(points:{x: number, y: number})`
|
||||
|
||||
Creates a continuous point set distribution using a list of points.
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`PointSet.makeContinuous([
|
||||
{ x: 0, y: 0.1 },
|
||||
{ x: 1, y: 0.2 },
|
||||
{ x: 2, y: 0.15 },
|
||||
{ x: 3, y: 0.1 }
|
||||
])`}
|
||||
/>
|
||||
|
||||
### Arguments
|
||||
|
||||
- `points`: An array of at least 3 coordinates.
|
||||
|
||||
## PointSet.makeDiscrete
|
||||
|
||||
`PointSet.makeDiscrete(points:{x: number, y: number})`
|
||||
|
||||
Creates a discrete point set distribution using a list of points.
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`PointSet.makeDiscrete([
|
||||
{ x: 0, y: 0.1 },
|
||||
{ x: 1, y: 0.2 },
|
||||
{ x: 2, y: 0.15 },
|
||||
{ x: 3, y: 0.1 }
|
||||
])`}
|
||||
/>
|
||||
|
||||
### Arguments
|
||||
|
||||
- `points`: An array of at least 1 coordinate.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
title: "Distribution Functions"
|
||||
title: "Distributions: Key Functions"
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
|
@ -181,7 +181,7 @@ The `sample(distribution)` samples a given distribution.
|
|||
|
||||
Recall the [three formats of distributions](https://develop--squiggle-documentation.netlify.app/docs/Discussions/Three-Types-Of-Distributions). We can force any distribution into `SampleSet` format
|
||||
|
||||
<SquiggleEditor defaultCode="PointSet.fromDist(normal(5, 10))" />
|
||||
<SquiggleEditor defaultCode="SampleSet.fromDist(normal(5, 10))" />
|
||||
|
||||
Or `PointSet` format
|
||||
|
||||
|
|
|
@ -5,50 +5,103 @@ title: Language Basics
|
|||
|
||||
import { SquiggleEditor } from "../../src/components/SquiggleEditor";
|
||||
|
||||
## Expressions
|
||||
Squiggle supports some simple types and language features.
|
||||
|
||||
### Numbers
|
||||
## Numbers
|
||||
|
||||
<SquiggleEditor defaultCode="4.32" />
|
||||
|
||||
### Distributions
|
||||
## Distributions
|
||||
|
||||
There are several ways of easily entering distributions. See the [documentation](/docs/Api/Dist/) on distributions for a complete API.
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`a = normal(4,2)
|
||||
b = 30 to 50
|
||||
c = lognormal({mean:90, stdev: 7})
|
||||
d = mixture(a,b,c, [0.3, 0.3, .4])
|
||||
{a:a, b:b, c:c, d:d}`}
|
||||
d = mixture(a,b,c, [.3, .3, .4])
|
||||
d`}
|
||||
/>
|
||||
|
||||
### Lists
|
||||
## Lists
|
||||
|
||||
Squiggle lists can accept items of any type, similar to those in Python. [API](/docs/Api/List).
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`[beta(1,10), 4, isNormalized(SampleSet.fromDist(1 to 2))]`}
|
||||
/>
|
||||
|
||||
<SquiggleEditor defaultCode={`List.make(5,1)`} />
|
||||
## Dictionaries
|
||||
|
||||
### Dictionaries
|
||||
Squiggle dictionaries work similarly to Python dictionaries. [API](/docs/Api/Dictionary).
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`d = {dist: triangular(0, 1, 2), weight: 0.25}
|
||||
d.dist`}
|
||||
/>
|
||||
|
||||
### Functions
|
||||
## Functions
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`f(t) = normal(t^2, t^1.2+.01)
|
||||
f`}
|
||||
/>
|
||||
|
||||
### Anonymous Functions
|
||||
## Anonymous Functions
|
||||
|
||||
<SquiggleEditor defaultCode={`{|t| normal(t^2, t^1.2+.01)}`} />
|
||||
|
||||
## See more
|
||||
## Comments
|
||||
|
||||
- [Distribution creation](./DistributionCreation)
|
||||
- [Functions reference](./Functions)
|
||||
- [Gallery](../Discussions/Gallery)
|
||||
<SquiggleEditor
|
||||
defaultCode={`// This is a single-line comment\n
|
||||
/*
|
||||
This is a multiple
|
||||
-line comment.
|
||||
*/
|
||||
""
|
||||
`}
|
||||
/>
|
||||
|
||||
## Pipes
|
||||
|
||||
Squiggle features [data-first](https://www.javierchavarri.com/data-first-and-data-last-a-comparison/) pipes. Functions in the standard library are organized to make this convenient.
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`normal(5,2) |> truncateLeft(3) |> SampleSet.fromDist |> SampleSet.map({|r| r + 10})`}
|
||||
/>
|
||||
|
||||
## Standard Library
|
||||
|
||||
Squiggle features a simple [standard libary](/docs/Api/Dist).
|
||||
|
||||
Most functions are namespaced under their respective types to keep functionality distinct. Certain popular functions are usable without their namespaces.
|
||||
|
||||
For example,
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`a = List.upTo(0, 5000) |> SampleSet.fromList // namespaces required
|
||||
b = normal(5,2) // namespace not required
|
||||
c = 5 to 10 // namespace not required
|
||||
""`}
|
||||
/>
|
||||
|
||||
## Number Prefixes
|
||||
|
||||
Numbers support a few scientific notation prefixes.
|
||||
|
||||
| prefix | multiplier |
|
||||
| ------ | ---------- |
|
||||
| n | 10^-9 |
|
||||
| m | 10^-3 |
|
||||
| k | 10^3 |
|
||||
| M | 10^6 |
|
||||
| B,G | 10^9 |
|
||||
| T | 10^12 |
|
||||
| P | 10^15 |
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`simpleNumber = 4.32k
|
||||
distribution = 40M to 50M
|
||||
distribution`}
|
||||
/>
|
||||
|
|
37
packages/website/docs/Internal/ImportIntoMdx.mdx
Normal file
37
packages/website/docs/Internal/ImportIntoMdx.mdx
Normal file
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
title: How to import squiggle files into `.mdx` documents
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
import { SquiggleEditorWithImportedBindings } from "../../src/components/SquiggleEditor";
|
||||
|
||||
_Proof of concept_
|
||||
|
||||
## Consider the following squiggle file
|
||||
|
||||
In our docusaurus repo, we have a static asset called `demo.squiggle`. It looks like this
|
||||
|
||||
```js
|
||||
x = 1 to 2
|
||||
y = {a: x, b: 1e1}
|
||||
f(t) = normal(t, 1.1)
|
||||
z = y.b * y.a
|
||||
```
|
||||
|
||||
We can call `f(z)` upon the assignments in `demo.squiggle` like so:
|
||||
|
||||
```jsx
|
||||
import { SquiggleEditorWithImportedBindings } from "../../src/components/SquiggleEditor";
|
||||
|
||||
<SquiggleEditorWithImportedBindings
|
||||
defaultCode={"f(z)"}
|
||||
bindingsImportFile={"/estimates/demo.squiggle"}
|
||||
/>;
|
||||
```
|
||||
|
||||
Which would then look exactly like
|
||||
|
||||
<SquiggleEditorWithImportedBindings
|
||||
defaultCode={"f(z)"}
|
||||
bindingsImportUrl={"/estimates/demo.squiggle"}
|
||||
/>
|
|
@ -1,30 +0,0 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
Squiggle is a simple programming language for intuitive probabilistic estimation. It's meant for quantitative forecasting and evaluations.
|
||||
|
||||
The basics of Squiggle can be pretty simple and intuitive. The more advanced functionality can take some time to learn.
|
||||
|
||||
## What Squiggle Is
|
||||
|
||||
- A simple programming language for doing math with probability distributions
|
||||
- An embeddable language that can be used in Javascript applications
|
||||
- A tool to embed functions as forecasts that can be embedded in other applications
|
||||
|
||||
## What Squiggle Is Not
|
||||
|
||||
- A complete replacement for enterprise Risk Analysis tools (See Crystal Ball, @Risk, Lumina Analytica)
|
||||
- A Probabilistic Programming Language with backwards inference and sophisticated sampling algorithms. (See [PPLs](https://en.wikipedia.org/wiki/Probabilistic_programming))
|
||||
- A visual tool aimed at casual users (see Guesstimate, Causal)
|
||||
|
||||
## Get started
|
||||
|
||||
- [Gallery](./Discussions/Gallery)
|
||||
- [Squiggle playground](/playground)
|
||||
- [Language basics](./Guides/Language)
|
||||
- [Squiggle functions source of truth](./Guides/Functions)
|
||||
- [Known bugs](./Discussions/Bugs)
|
||||
- [Original lesswrong sequence](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3)
|
||||
- [Author your squiggle models as Observable notebooks](https://observablehq.com/@hazelfire/squiggle)
|
119
packages/website/docs/Overview.mdx
Normal file
119
packages/website/docs/Overview.mdx
Normal file
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
sidebar_position: 1
|
||||
title: Overview
|
||||
---
|
||||
|
||||
import { SquiggleEditor } from "../src/components/SquiggleEditor";
|
||||
|
||||
Squiggle is a minimalist programming language for probabilistic estimation. It's meant for intuitively-driven quantitative estimation instead of data analysis or data-driven statistical techniques.
|
||||
|
||||
The basics of Squiggle are fairly straightforward. This can be enough for many models. The more advanced functionality can take some time to learn.
|
||||
|
||||
## Simple example
|
||||
|
||||
Say you're trying to estimate the number of piano tuners in New York City. You can build a simple model of this, like so.
|
||||
(Tip: This is interactive! Feel free to modify the code directly.)
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`
|
||||
// Piano tuners in NYC over the next 5 years
|
||||
populationOfNewYork2022 = 8.1M to 8.4M // This means that you're 90% confident the value is between 8.1 and 8.4 Million.\n
|
||||
proportionOfPopulationWithPianos = {
|
||||
percentage = (.2 to 1)
|
||||
percentage * 0.01
|
||||
} // We assume there are almost no people with multiple pianos\n
|
||||
pianoTunersPerPiano = {
|
||||
pianosPerPianoTuner = 2k to 50k // This is artificially narrow, to help graphics later
|
||||
1 / pianosPerPianoTuner
|
||||
} \n
|
||||
totalTunersIn2022 = populationOfNewYork2022 * proportionOfPopulationWithPianos * pianoTunersPerPiano
|
||||
totalTunersIn2022
|
||||
`}
|
||||
/>
|
||||
|
||||
---
|
||||
|
||||
Now let's take this a bit further. Let's imagine that you think that NYC will grow over time, and you'd like to estimate the number of piano tuners for every point in time for the next few years.
|
||||
|
||||
<SquiggleEditor
|
||||
defaultCode={`// Piano tuners in NYC over the next 5 years
|
||||
populationOfNewYork2022 = 8.1M to 8.4M\n
|
||||
proportionOfPopulationWithPianos = {
|
||||
percentage = (.2 to 1)
|
||||
percentage * 0.01
|
||||
} // We assume there are almost no people with multiple pianos\n
|
||||
pianoTunersPerPiano = {
|
||||
pianosPerPianoTuner = 2k to 50k // This is artificially narrow, to help graphics later
|
||||
1 / pianosPerPianoTuner
|
||||
} \n
|
||||
//Time in years after 2022
|
||||
populationAtTime(t) = {
|
||||
averageYearlyPercentageChange = -0.01 to 0.05 // We're expecting NYC to continuously grow with an mean of roughly between -1% and +4% per year
|
||||
populationOfNewYork2022 * ((averageYearlyPercentageChange + 1) ^ t)
|
||||
}\n
|
||||
median(v) = quantile(v, .5)
|
||||
totalTunersAtTime(t) = populationAtTime(t) * proportionOfPopulationWithPianos * pianoTunersPerPiano\n
|
||||
{
|
||||
populationAtTime: populationAtTime,
|
||||
totalTunersAtTimeMedian: {|t| median(totalTunersAtTime(t))}
|
||||
}`}
|
||||
/>
|
||||
|
||||
If you haven't noticed yet, you can hover over the `populationAtTime` graph to see the distribution of population at different points in time.
|
||||
|
||||
## Using Squiggle
|
||||
|
||||
You can currently interact with Squiggle in a few ways:
|
||||
|
||||
**[Playground](/playground)**
|
||||
The [Squiggle Playground](/playground) is a nice tool for working with small models and making prototypes. You can make simple shareable links, but you can't save models that change over time.
|
||||
|
||||
**[Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=QURI.vscode-squiggle)**
|
||||
There's a simple [VS Code extension](https://marketplace.visualstudio.com/items?itemName=QURI.vscode-squiggle) for running and visualizing Squiggle code. We find that VS Code is a useful editor for managing larger Squiggle setups.
|
||||
|
||||
**[Typescript Library](https://www.npmjs.com/package/@quri/squiggle-lang)**
|
||||
Squiggle is built using [Rescript](https://rescript-lang.org/), and is accessible via a simple Typescript library. You can use this library to either run Squiggle code in full, or to call select specific functions within Squiggle (though this latter functionality is very minimal).
|
||||
|
||||
**[React Components Library](https://www.npmjs.com/package/@quri/squiggle-components)**
|
||||
All of the components used in the playground and documentation are available in a separate component NPM repo. You can see the full Storybook of components [here](https://squiggle-components.netlify.app).
|
||||
|
||||
**[Observable](https://observablehq.com/@hazelfire/squiggle)**
|
||||
You can use Squiggle Components in Observable notebooks. Sam Nolan put together an exportable [Observable Notebook](https://observablehq.com/@hazelfire/squiggle) of the key components that you can directly import and use in your Observable notebooks.
|
||||
|
||||
## Squiggle Vs. Other Tools
|
||||
|
||||
### What Squiggle Is
|
||||
|
||||
- A simple programming language for doing math with probability distributions.
|
||||
- An embeddable language that can be used in Javascript applications.
|
||||
- A tool to encode functions as forecasts that can be embedded in other applications.
|
||||
|
||||
### What Squiggle Is Not
|
||||
|
||||
- A complete replacement for enterprise Risk Analysis tools. (See [Crystal Ball](https://www.oracle.com/applications/crystalball/), [@Risk](https://www.palisade.com/risk/), [Lumina Analytica](https://lumina.com/))
|
||||
- A [probabilistic programming language](https://en.wikipedia.org/wiki/Probabilistic_programming). Squiggle does not support Bayesian inference.
|
||||
- A tool for substantial data analysis. (See programming languages like [Python](https://www.python.org/) or [Julia](https://julialang.org/))
|
||||
- A programming language for anything other than estimation.
|
||||
- A visually-driven tool. (See [Guesstimate](https://www.getguesstimate.com/) and [Causal](https://causal.app/))
|
||||
|
||||
### Strengths
|
||||
|
||||
- Simple and readable syntax, especially for dealing with probabilistic math.
|
||||
- Fast for relatively small models. Strong for rapid prototyping.
|
||||
- Optimized for using some numeric and symbolic approaches, not just Monte Carlo.
|
||||
- Embeddable in Javascript.
|
||||
- Free and open-source.
|
||||
|
||||
### Weaknesses
|
||||
|
||||
- Limited scientific capabilities.
|
||||
- Much slower than serious probabilistic programming languages on sizeable models.
|
||||
- Can't do Bayesian backwards inference.
|
||||
- Essentially no support for libraries or modules (yet).
|
||||
- Still very new, so a tiny ecosystem.
|
||||
- Still very new, so there are likely math bugs.
|
||||
- Generally not as easy to use as Guesstimate or Causal, especially for non programmers.
|
||||
|
||||
## Organization
|
||||
|
||||
Squiggle is one of the main projects of [The Quantified Uncertainty Research Institute](https://quantifieduncertainty.org/). QURI is a nonprofit funded primarily by [Effective Altruist](https://www.effectivealtruism.org/) donors.
|
|
@ -57,18 +57,18 @@ const config = {
|
|||
hideOnScroll: true,
|
||||
logo: {
|
||||
alt: "Squiggle Logo",
|
||||
src: "img/quri-logo.png",
|
||||
src: "img/squiggle-logo.png",
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: "doc",
|
||||
docId: "Introduction",
|
||||
docId: "Overview",
|
||||
position: "left",
|
||||
label: "Documentation",
|
||||
},
|
||||
{
|
||||
type: "doc",
|
||||
docId: "Api/DistGeneric",
|
||||
docId: "Api/Dist",
|
||||
position: "left",
|
||||
label: "API",
|
||||
},
|
||||
|
@ -84,6 +84,11 @@ const config = {
|
|||
label: "GitHub",
|
||||
position: "right",
|
||||
},
|
||||
{
|
||||
href: "https://quantifieduncertainty.org/",
|
||||
label: "QURI",
|
||||
position: "right",
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"@docusaurus/core": "2.0.0-rc.1",
|
||||
"@docusaurus/preset-classic": "2.0.0-rc.1",
|
||||
"@heroicons/react": "^1.0.6",
|
||||
"@quri/squiggle-components": "^0.2.20",
|
||||
"@quri/squiggle-components": "^0.2.23",
|
||||
"base64-js": "^1.5.1",
|
||||
"clsx": "^1.2.1",
|
||||
"hast-util-is-element": "2.1.2",
|
||||
|
|
|
@ -23,8 +23,8 @@ const sidebars = {
|
|||
tutorialSidebar: [
|
||||
{
|
||||
type: "doc",
|
||||
id: "Introduction",
|
||||
label: "Introduction",
|
||||
id: "Overview",
|
||||
label: "Overview",
|
||||
},
|
||||
{
|
||||
type: "doc",
|
||||
|
|
|
@ -12,3 +12,15 @@ export function SquiggleEditor(props) {
|
|||
</BrowserOnly>
|
||||
);
|
||||
}
|
||||
|
||||
export function SquiggleEditorWithImportedBindings(props) {
|
||||
return (
|
||||
<BrowserOnly fallback={<FallbackSpinner height={292} />}>
|
||||
{() => {
|
||||
const LibComponent =
|
||||
require("@quri/squiggle-components").SquiggleEditorWithImportedBindings;
|
||||
return <LibComponent {...props} />;
|
||||
}}
|
||||
</BrowserOnly>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ html[data-theme="dark"] .docusaurus-highlight-code-line {
|
|||
}
|
||||
|
||||
.hero__subtitle2 {
|
||||
color: #ba3e3e;
|
||||
color: #777;
|
||||
font-size: 1.5em;
|
||||
font-family: "Lora";
|
||||
font-weight: 500;
|
||||
|
@ -88,6 +88,10 @@ h2 {
|
|||
font-weight: 700;
|
||||
}
|
||||
|
||||
.navbar__logo {
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
:root {
|
||||
/* --ifm-font-family-base: 'Lora'; */
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React from "react";
|
||||
import clsx from "clsx";
|
||||
import Layout from "@theme/Layout";
|
||||
import Link from "@docusaurus/Link";
|
||||
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
||||
import styles from "./index.module.css";
|
||||
import HomepageFeatures from "../components/HomepageFeatures";
|
||||
|
@ -11,6 +10,12 @@ function HomepageHeader() {
|
|||
return (
|
||||
<header className={clsx("hero hero--primary", styles.heroBanner)}>
|
||||
<div className="container">
|
||||
<img
|
||||
alt={"Docusaurus with Keytar"}
|
||||
className={styles.heroLogo}
|
||||
src={"/img/squiggle-logo.png"}
|
||||
width="70"
|
||||
/>
|
||||
<h1 className="hero__title">{siteConfig.title}</h1>
|
||||
<p className="hero__subtitle">Early Access</p>
|
||||
<p className="hero__subtitle2">{siteConfig.tagline}</p>
|
||||
|
|
|
@ -44,6 +44,7 @@ export default function PlaygroundPage() {
|
|||
const playgroundProps = {
|
||||
defaultCode: "normal(0,1)",
|
||||
height: 700,
|
||||
showShareButton: true,
|
||||
...hashData,
|
||||
onCodeChange: (code) => setHashData({ initialSquiggleString: code }),
|
||||
onSettingsChange: (settings) => {
|
||||
|
|
4
packages/website/static/estimates/demo.squiggle
Normal file
4
packages/website/static/estimates/demo.squiggle
Normal file
|
@ -0,0 +1,4 @@
|
|||
x = 1 to 2
|
||||
y = {a: x, b: 1e1}
|
||||
f(t) = normal(t, 1.1)
|
||||
z = y.b * y.a
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
BIN
packages/website/static/img/squiggle-logo.png
Normal file
BIN
packages/website/static/img/squiggle-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Loading…
Reference in New Issue
Block a user