Merge branch 'develop' into Umur-develop
18
README.md
|
@ -1,12 +1,22 @@
|
||||||
# Squiggle
|
# Squiggle
|
||||||
|
|
||||||
[![Packages check](https://github.com/quantified-uncertainty/squiggle/actions/workflows/ci.yml/badge.svg)](https://github.com/quantified-uncertainty/squiggle/actions/workflows/ci.yml)
|
[![Packages check](https://github.com/quantified-uncertainty/squiggle/actions/workflows/ci.yml/badge.svg)](https://github.com/quantified-uncertainty/squiggle/actions/workflows/ci.yml)
|
||||||
[![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-lang.svg)](https://www.npmjs.com/package/@quri/squiggle-lang)
|
[![npm version - lang](https://badge.fury.io/js/@quri%2Fsquiggle-lang.svg)](https://www.npmjs.com/package/@quri/squiggle-lang)
|
||||||
[![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-components.svg)](https://www.npmjs.com/package/@quri/squiggle-components)
|
[![npm version - components](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)
|
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/quantified-uncertainty/squiggle/blob/develop/LICENSE)
|
||||||
[![codecov](https://codecov.io/gh/quantified-uncertainty/squiggle/branch/develop/graph/badge.svg?token=QRLBL5CQ7C)](https://codecov.io/gh/quantified-uncertainty/squiggle)
|
[![codecov](https://codecov.io/gh/quantified-uncertainty/squiggle/branch/develop/graph/badge.svg?token=QRLBL5CQ7C)](https://codecov.io/gh/quantified-uncertainty/squiggle)
|
||||||
|
|
||||||
This is an experimental DSL/language for making probabilistic estimates. The full story can be found [here](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3).
|
_An estimation language_.
|
||||||
|
|
||||||
|
## Get started
|
||||||
|
|
||||||
|
- [Gallery](https://www.squiggle-language.com/docs/Discussions/Gallery)
|
||||||
|
- [Squiggle playground](https://squiggle-language.com/playground)
|
||||||
|
- [Language basics](https://www.squiggle-language.com/docs/Features/Language)
|
||||||
|
- [Squiggle functions source of truth](https://www.squiggle-language.com/docs/Features/Functions)
|
||||||
|
- [Known bugs](https://www.squiggle-language.com/docs/Discussions/Bugs)
|
||||||
|
- [Original lesswrong sequence](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3)
|
||||||
|
- [Author your squiggle models as Observable notebooks](https://observablehq.com/@hazelfire/squiggle)
|
||||||
|
|
||||||
## Our deployments
|
## Our deployments
|
||||||
|
|
||||||
|
@ -27,7 +37,7 @@ the packages can be found in `packages`.
|
||||||
- `@quri/squiggle-components` in `packages/components` contains React components that
|
- `@quri/squiggle-components` in `packages/components` contains React components that
|
||||||
can be passed squiggle strings as props, and return a presentation of the result
|
can be passed squiggle strings as props, and return a presentation of the result
|
||||||
of the calculation.
|
of the calculation.
|
||||||
- `@quri/squiggle-website` in `packages/website` The main descriptive website for squiggle,
|
- `packages/website` is the main descriptive website for squiggle,
|
||||||
it is hosted at `squiggle-language.com`.
|
it is hosted at `squiggle-language.com`.
|
||||||
|
|
||||||
The playground depends on the components library which then depends on the language. This means that if you wish to work on the components library, you will need to build (no need to bundle) the language, and as of this writing playground doesn't really work.
|
The playground depends on the components library which then depends on the language. This means that if you wish to work on the components library, you will need to build (no need to bundle) the language, and as of this writing playground doesn't really work.
|
||||||
|
|
20
examples/decay.squiggle
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# The following code was provided by Nuño Sempere, it comes directly from the post https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3/p/j8o6sgRerE3tqNWdj
|
||||||
|
## Initial setup
|
||||||
|
yearly_probability_max = 0.95
|
||||||
|
yearly_probability_min = 0.66
|
||||||
|
period_probability_function(epsilon, yearly_probability) = 1 - (1 - yearly_probability) ^ (1 / epsilon)
|
||||||
|
probability_decayed(t, time_periods, period_probability) = 1 - (1 - period_probability) ^ (time_periods - t)
|
||||||
|
|
||||||
|
## Monthly decomposition
|
||||||
|
months_in_a_year=12
|
||||||
|
|
||||||
|
monthly_probability_min = period_probability_function(months_in_a_year, yearly_probability_min)
|
||||||
|
monthly_probability_max = period_probability_function(months_in_a_year, yearly_probability_max)
|
||||||
|
|
||||||
|
probability_decayed_monthly_min(t) = probability_decayed(t, months_in_a_year, monthly_probability_min)
|
||||||
|
probability_decayed_monthly_max(t) = probability_decayed(t, months_in_a_year, monthly_probability_max)
|
||||||
|
probability_decayed_monthly(t) = probability_decayed_monthly_min(t) to probability_decayed_monthly_max(t)
|
||||||
|
|
||||||
|
probability_decayed_monthly
|
||||||
|
## probability_decayed_monthly(6)
|
||||||
|
## mean(probability_decayed_monthly(6))
|
38
examples/givedirectly.squiggle
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# This is a cost effectiveness analysis of givedirectly, originally done by givewell, and translated into Squiggle by Sam Nolan
|
||||||
|
donation_size = 10000
|
||||||
|
proportion_of_funding_available = beta(10, 2)
|
||||||
|
total_funding_available = donation_size * proportion_of_funding_available
|
||||||
|
household_size = 3.7 to 5.7
|
||||||
|
size_of_transfer = 800 to 1200
|
||||||
|
size_of_transfer_per_person = size_of_transfer / household_size
|
||||||
|
|
||||||
|
portion_invested = 0.3 to 0.5
|
||||||
|
amount_invested = portion_invested * size_of_transfer_per_person
|
||||||
|
amount_consumed = (1 - portion_invested) * size_of_transfer_per_person
|
||||||
|
return_on_investment = 0.08 to 0.12
|
||||||
|
increase_in_consumption_from_investments = return_on_investment * amount_invested
|
||||||
|
baseline_consumption = 200 to 350
|
||||||
|
log_increase_in_consumption = log(amount_consumed + baseline_consumption) + log(baseline_consumption)
|
||||||
|
log_increase_in_consumption_from_investment = log(increase_in_consumption_from_investments + baseline_consumption) + log(baseline_consumption)
|
||||||
|
investment_duration = 8 to 12
|
||||||
|
discount_rate = beta(1.004, 20)
|
||||||
|
|
||||||
|
present_value_excluding_last_year = log_increase_in_consumption_from_investment * (1 - (1 + discount_rate) ^ (-investment_duration)) / (log(1 + discount_rate))
|
||||||
|
|
||||||
|
percent_of_investment_returned = 0.15 to 0.25
|
||||||
|
|
||||||
|
pv_consumption_last_year = (log(baseline_consumption + amount_invested * (return_on_investment + percent_of_investment_returned)) - log(baseline_consumption)) / (1 + discount_rate)^investment_duration
|
||||||
|
|
||||||
|
total_pv_of_cash_transfer = pv_consumption_last_year + present_value_excluding_last_year + log_increase_in_consumption
|
||||||
|
|
||||||
|
discount_negative_spoiler = 0.03 to 0.07
|
||||||
|
|
||||||
|
value_discounting_spoiler = discount_negative_spoiler * total_pv_of_cash_transfer
|
||||||
|
|
||||||
|
consumption_increase_per_household = value_discounting_spoiler * household_size
|
||||||
|
|
||||||
|
amount_of_transfers_made = total_funding_available / size_of_transfer
|
||||||
|
|
||||||
|
total_increase_in_ln_consumption = amount_of_transfers_made * consumption_increase_per_household
|
||||||
|
|
||||||
|
total_increase_in_ln_consumption
|
3
examples/wholenumberassignmentevaluation.squiggle
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
xY1 = 99
|
||||||
|
aBa3 = xY1 * 2 + 1
|
||||||
|
aBa3 * xY1 + aBa3
|
|
@ -1,8 +1,26 @@
|
||||||
|
[![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 all the components for squiggle. These can be used either as a library or hosted as a [storybook](https://storybook.js.org/).
|
||||||
|
|
||||||
# Build for development
|
# Usage in a `react` project
|
||||||
|
|
||||||
|
For example, in a fresh `create-react-app` project
|
||||||
|
|
||||||
|
```sh
|
||||||
|
yarn add @quri/squiggle-components
|
||||||
|
```
|
||||||
|
|
||||||
|
Add to `App.js`:
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import { SquiggleEditor } from "@quri/squiggle-components";
|
||||||
|
<SquiggleEditor initialSquiggleString="x = beta(3, 10); x + 20" />;
|
||||||
|
```
|
||||||
|
|
||||||
|
# Build storybook for development
|
||||||
|
|
||||||
We assume that you had run `yarn` at monorepo level, installing dependencies.
|
We assume that you had run `yarn` at monorepo level, installing dependencies.
|
||||||
|
|
||||||
|
@ -24,6 +42,5 @@ yarn start
|
||||||
And build artefacts for production,
|
And build artefacts for production,
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn bundle # builds components library
|
|
||||||
yarn build # builds storybook app
|
yarn build # builds storybook app
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
{
|
{
|
||||||
"name": "@quri/squiggle-components",
|
"name": "@quri/squiggle-components",
|
||||||
"version": "0.2.9",
|
"version": "0.2.14",
|
||||||
"licence": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"antd": "^4.20.1",
|
|
||||||
"react-ace": "10.1.0",
|
"react-ace": "10.1.0",
|
||||||
|
"@quri/squiggle-lang": "^0.2.7",
|
||||||
"react-dom": "^18.1.0",
|
"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",
|
||||||
"@react-hook/size": "^2.1.2",
|
"@react-hook/size": "^2.1.2",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"styled-components": "^5.3.5"
|
"styled-components": "^5.3.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -26,31 +32,25 @@
|
||||||
"webpack": "^5.72.0",
|
"webpack": "^5.72.0",
|
||||||
"webpack-cli": "^4.9.2",
|
"webpack-cli": "^4.9.2",
|
||||||
"webpack-dev-server": "^4.8.1",
|
"webpack-dev-server": "^4.8.1",
|
||||||
"@quri/squiggle-lang": "0.2.5",
|
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"@testing-library/jest-dom": "^5.16.4",
|
||||||
"@testing-library/react": "^13.1.1",
|
"@testing-library/react": "^13.1.1",
|
||||||
"@testing-library/user-event": "^14.1.1",
|
"@testing-library/user-event": "^14.1.1",
|
||||||
"@types/jest": "^27.4.0",
|
"@types/jest": "^27.4.0",
|
||||||
|
"web-vitals": "^2.1.4",
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.14.182",
|
||||||
"@types/node": "^17.0.29",
|
"@types/node": "^17.0.29",
|
||||||
"@types/react": "^18.0.3",
|
"@types/react": "^18.0.3",
|
||||||
"@types/react-dom": "^18.0.2",
|
"@types/react-dom": "^18.0.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"lodash": "^4.17.21",
|
|
||||||
"react": "^18.1.0",
|
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"react-vega": "^7.5.0",
|
|
||||||
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
"tsconfig-paths-webpack-plugin": "^3.5.2",
|
||||||
"typescript": "^4.6.3",
|
"typescript": "^4.6.3",
|
||||||
"vega": "^5.22.1",
|
|
||||||
"vega-embed": "^6.20.6",
|
|
||||||
"vega-lite": "^5.2.0",
|
|
||||||
"web-vitals": "^2.1.4",
|
|
||||||
"webpack-cli": "^4.9.2"
|
"webpack-cli": "^4.9.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
|
"start": "cross-env REACT_APP_FAST_REFRESH=false && start-storybook -p 6006 -s public",
|
||||||
"build": "tsc -b && build-storybook -s public",
|
"build": "tsc -b && build-storybook -s public",
|
||||||
|
"build:package": "tsc -b",
|
||||||
"bundle": "webpack",
|
"bundle": "webpack",
|
||||||
"all": "yarn bundle && yarn build",
|
"all": "yarn bundle && yarn build",
|
||||||
"lint": "prettier --check .",
|
"lint": "prettier --check .",
|
||||||
|
@ -88,6 +88,7 @@
|
||||||
"@types/react": "17.0.43"
|
"@types/react": "17.0.43"
|
||||||
},
|
},
|
||||||
"source": "./src/index.ts",
|
"source": "./src/index.ts",
|
||||||
"main": "dist/bundle.js",
|
"browser": "dist/bundle.js",
|
||||||
|
"main": "dist/src/index.js",
|
||||||
"types": "dist/src/index.d.ts"
|
"types": "dist/src/index.d.ts"
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { distributionErrorToString } from "@quri/squiggle-lang";
|
||||||
import { createClassFromSpec } from "react-vega";
|
import { createClassFromSpec } from "react-vega";
|
||||||
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorBox } from "./ErrorBox";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
let SquiggleVegaChart = createClassFromSpec({
|
let SquiggleVegaChart = createClassFromSpec({
|
||||||
spec: chartSpecification as Spec,
|
spec: chartSpecification as Spec,
|
||||||
|
@ -24,19 +25,21 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
|
||||||
}: DistributionChartProps) => {
|
}: DistributionChartProps) => {
|
||||||
let shape = distribution.pointSet();
|
let shape = distribution.pointSet();
|
||||||
if (shape.tag === "Ok") {
|
if (shape.tag === "Ok") {
|
||||||
return (
|
let widthProp = width ? width - 20 : undefined;
|
||||||
|
var result = (
|
||||||
<SquiggleVegaChart
|
<SquiggleVegaChart
|
||||||
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
|
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
|
||||||
width={width - 20}
|
width={widthProp}
|
||||||
height={height}
|
height={height}
|
||||||
actions={false}
|
actions={false}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
var result = (
|
||||||
<ErrorBox heading="Distribution Error">
|
<ErrorBox heading="Distribution Error">
|
||||||
{distributionErrorToString(shape.value)}
|
{distributionErrorToString(shape.value)}
|
||||||
</ErrorBox>
|
</ErrorBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,10 +3,12 @@ import _ from "lodash";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import {
|
import {
|
||||||
run,
|
run,
|
||||||
|
runPartial,
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
squiggleExpression,
|
squiggleExpression,
|
||||||
|
bindings,
|
||||||
|
samplingParams,
|
||||||
} from "@quri/squiggle-lang";
|
} from "@quri/squiggle-lang";
|
||||||
import type { samplingParams } from "@quri/squiggle-lang";
|
|
||||||
import { NumberShower } from "./NumberShower";
|
import { NumberShower } from "./NumberShower";
|
||||||
import { DistributionChart } from "./DistributionChart";
|
import { DistributionChart } from "./DistributionChart";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorBox } from "./ErrorBox";
|
||||||
|
@ -44,6 +46,8 @@ export const VariableBox: React.FC<{
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let RecordKeyHeader = styled.h3``;
|
||||||
|
|
||||||
export interface SquiggleItemProps {
|
export interface SquiggleItemProps {
|
||||||
/** The input string for squiggle */
|
/** The input string for squiggle */
|
||||||
expression: squiggleExpression;
|
expression: squiggleExpression;
|
||||||
|
@ -104,6 +108,17 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
))}
|
))}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
|
case "record":
|
||||||
|
return (
|
||||||
|
<VariableBox heading="Record">
|
||||||
|
{Object.entries(expression.value).map(([key, r]) => (
|
||||||
|
<>
|
||||||
|
<RecordKeyHeader>{key}</RecordKeyHeader>
|
||||||
|
<SquiggleItem expression={r} width={width - 20} height={50} />
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</VariableBox>
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return (
|
return (
|
||||||
<ErrorBox heading="No Viewer">
|
<ErrorBox heading="No Viewer">
|
||||||
|
@ -135,40 +150,43 @@ export interface SquiggleChartProps {
|
||||||
/** CSS width of the element */
|
/** CSS width of the element */
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
/** Bindings of previous variables declared */
|
||||||
|
bindings?: bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ChartWrapper = styled.div`
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
|
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
|
||||||
|
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
`;
|
||||||
|
|
||||||
export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
squiggleString = "",
|
squiggleString = "",
|
||||||
sampleCount = 1000,
|
sampleCount = 1000,
|
||||||
outputXYPoints = 1000,
|
outputXYPoints = 1000,
|
||||||
onChange = () => {},
|
onChange = () => {},
|
||||||
height = 60,
|
height = 60,
|
||||||
|
bindings = {},
|
||||||
width = NaN,
|
width = NaN,
|
||||||
}: SquiggleChartProps) => {
|
}: SquiggleChartProps) => {
|
||||||
const target = React.useRef(null);
|
|
||||||
const [componentWidth] = useSize(target);
|
|
||||||
// I would have wanted to just use componentWidth, but this created infinite loops with SquiggleChart.stories.
|
|
||||||
//So you can manually add a width, as an escape hatch.
|
|
||||||
let _width = width || componentWidth;
|
|
||||||
let samplingInputs: samplingParams = {
|
let samplingInputs: samplingParams = {
|
||||||
sampleCount: sampleCount,
|
sampleCount: sampleCount,
|
||||||
xyPointLength: outputXYPoints,
|
xyPointLength: outputXYPoints,
|
||||||
};
|
};
|
||||||
let expressionResult = run(squiggleString, samplingInputs);
|
let expressionResult = run(squiggleString, bindings, samplingInputs);
|
||||||
let internal: JSX.Element;
|
let internal: JSX.Element;
|
||||||
if (expressionResult.tag === "Ok") {
|
if (expressionResult.tag === "Ok") {
|
||||||
let expression = expressionResult.value;
|
let expression = expressionResult.value;
|
||||||
onChange(expression);
|
onChange(expression);
|
||||||
internal = (
|
internal = (
|
||||||
<SquiggleItem expression={expression} width={_width} height={height} />
|
<SquiggleItem expression={expression} width={width} height={height} />
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// At this point, we came across an error. What was our error?
|
|
||||||
internal = (
|
internal = (
|
||||||
<ErrorBox heading={"Parse Error"}>
|
<ErrorBox heading={"Parse Error"}>
|
||||||
{errorValueToString(expressionResult.value)}
|
{errorValueToString(expressionResult.value)}
|
||||||
</ErrorBox>
|
</ErrorBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return <div ref={target}>{internal}</div>;
|
return <ChartWrapper>{internal}</ChartWrapper>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,9 @@ import * as ReactDOM from "react-dom";
|
||||||
import { SquiggleChart } from "./SquiggleChart";
|
import { SquiggleChart } from "./SquiggleChart";
|
||||||
import { CodeEditor } from "./CodeEditor";
|
import { CodeEditor } from "./CodeEditor";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import type { squiggleExpression } from "@quri/squiggle-lang";
|
import type { squiggleExpression, bindings } from "@quri/squiggle-lang";
|
||||||
|
import { runPartial, errorValueToString } from "@quri/squiggle-lang";
|
||||||
|
import { ErrorBox } from "./ErrorBox";
|
||||||
|
|
||||||
export interface SquiggleEditorProps {
|
export interface SquiggleEditorProps {
|
||||||
/** The input string for squiggle */
|
/** The input string for squiggle */
|
||||||
|
@ -26,6 +28,8 @@ export interface SquiggleEditorProps {
|
||||||
onChange?(expr: squiggleExpression): void;
|
onChange?(expr: squiggleExpression): void;
|
||||||
/** The width of the element */
|
/** The width of the element */
|
||||||
width: number;
|
width: number;
|
||||||
|
/** Previous variable declarations */
|
||||||
|
bindings: bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Input = styled.div`
|
const Input = styled.div`
|
||||||
|
@ -46,6 +50,7 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
||||||
diagramCount,
|
diagramCount,
|
||||||
onChange,
|
onChange,
|
||||||
environment,
|
environment,
|
||||||
|
bindings = {},
|
||||||
}: SquiggleEditorProps) => {
|
}: SquiggleEditorProps) => {
|
||||||
let [expression, setExpression] = React.useState(initialSquiggleString);
|
let [expression, setExpression] = React.useState(initialSquiggleString);
|
||||||
return (
|
return (
|
||||||
|
@ -71,6 +76,7 @@ export let SquiggleEditor: React.FC<SquiggleEditorProps> = ({
|
||||||
diagramCount={diagramCount}
|
diagramCount={diagramCount}
|
||||||
environment={environment}
|
environment={environment}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
bindings={bindings}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -107,3 +113,76 @@ export function renderSquiggleEditorToDom(props: SquiggleEditorProps) {
|
||||||
);
|
);
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SquigglePartialProps {
|
||||||
|
/** The input string for squiggle */
|
||||||
|
initialSquiggleString?: string;
|
||||||
|
/** If the output requires monte carlo sampling, the amount of samples */
|
||||||
|
sampleCount?: number;
|
||||||
|
/** The amount of points returned to draw the distribution */
|
||||||
|
outputXYPoints?: number;
|
||||||
|
kernelWidth?: number;
|
||||||
|
pointDistLength?: number;
|
||||||
|
/** If the result is a function, where the function starts */
|
||||||
|
diagramStart?: number;
|
||||||
|
/** If the result is a function, where the function ends */
|
||||||
|
diagramStop?: number;
|
||||||
|
/** If the result is a function, how many points along the function it samples */
|
||||||
|
diagramCount?: number;
|
||||||
|
/** when the environment changes. Used again for notebook magic*/
|
||||||
|
onChange?(expr: bindings): void;
|
||||||
|
/** The width of the element */
|
||||||
|
width: number;
|
||||||
|
/** Previously declared variables */
|
||||||
|
bindings: bindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
export let SquigglePartial: React.FC<SquigglePartialProps> = ({
|
||||||
|
initialSquiggleString = "",
|
||||||
|
onChange,
|
||||||
|
bindings,
|
||||||
|
}: SquigglePartialProps) => {
|
||||||
|
let [expression, setExpression] = React.useState(initialSquiggleString);
|
||||||
|
let squiggleResult = runPartial(expression, bindings);
|
||||||
|
if (squiggleResult.tag == "Ok") {
|
||||||
|
if (onChange) onChange(squiggleResult.value);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Input>
|
||||||
|
<CodeEditor
|
||||||
|
value={expression}
|
||||||
|
onChange={setExpression}
|
||||||
|
oneLine={true}
|
||||||
|
showGutter={false}
|
||||||
|
height={20}
|
||||||
|
/>
|
||||||
|
</Input>
|
||||||
|
{squiggleResult.tag == "Error" ? (
|
||||||
|
<ErrorBox heading="Error">
|
||||||
|
{errorValueToString(squiggleResult.value)}
|
||||||
|
</ErrorBox>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function renderSquigglePartialToDom(props: SquigglePartialProps) {
|
||||||
|
let parent = document.createElement("div");
|
||||||
|
ReactDOM.render(
|
||||||
|
<SquigglePartial
|
||||||
|
{...props}
|
||||||
|
onChange={(bindings) => {
|
||||||
|
// @ts-ignore
|
||||||
|
parent.value = bindings;
|
||||||
|
|
||||||
|
parent.dispatchEvent(new CustomEvent("input"));
|
||||||
|
if (props.onChange) props.onChange(bindings);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
parent
|
||||||
|
);
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React, { FC, useState } from "react";
|
import React, { FC, ReactElement, useState } from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import { SquiggleChart } from "./SquiggleChart";
|
import { SquiggleChart } from "./SquiggleChart";
|
||||||
import CodeEditor from "./CodeEditor";
|
import CodeEditor from "./CodeEditor";
|
||||||
import { Form, Input, Row, Col } from "antd";
|
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import "antd/dist/antd.css";
|
|
||||||
|
|
||||||
interface FieldFloatProps {
|
interface FieldFloatProps {
|
||||||
label: string;
|
label: string;
|
||||||
|
@ -14,10 +12,19 @@ interface FieldFloatProps {
|
||||||
onChange: (value: number) => void;
|
onChange: (value: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Input = styled.input``;
|
||||||
|
|
||||||
|
const FormItem = (props: { label: string; children: ReactElement }) => (
|
||||||
|
<div>
|
||||||
|
<label>{props.label}</label>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
function FieldFloat(Props: FieldFloatProps) {
|
function FieldFloat(Props: FieldFloatProps) {
|
||||||
let [contents, setContents] = useState(Props.value + "");
|
let [contents, setContents] = useState(Props.value + "");
|
||||||
return (
|
return (
|
||||||
<Form.Item label={Props.label}>
|
<FormItem label={Props.label}>
|
||||||
<Input
|
<Input
|
||||||
value={contents}
|
value={contents}
|
||||||
className={Props.className ? Props.className : ""}
|
className={Props.className ? Props.className : ""}
|
||||||
|
@ -29,7 +36,7 @@ function FieldFloat(Props: FieldFloatProps) {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</FormItem>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +72,12 @@ const Display = styled.div<TitleProps>`
|
||||||
max-height: ${(props) => props.maxHeight}px;
|
max-height: ${(props) => props.maxHeight}px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const Row = styled.div`
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
`;
|
||||||
|
const Col = styled.div``;
|
||||||
|
|
||||||
let SquigglePlayground: FC<Props> = ({
|
let SquigglePlayground: FC<Props> = ({
|
||||||
initialSquiggleString = "",
|
initialSquiggleString = "",
|
||||||
height = 300,
|
height = 300,
|
||||||
|
@ -79,7 +92,7 @@ let SquigglePlayground: FC<Props> = ({
|
||||||
return (
|
return (
|
||||||
<ShowBox height={height}>
|
<ShowBox height={height}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col span={12}>
|
<Col>
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
value={squiggleString}
|
value={squiggleString}
|
||||||
onChange={setSquiggleString}
|
onChange={setSquiggleString}
|
||||||
|
@ -88,7 +101,7 @@ let SquigglePlayground: FC<Props> = ({
|
||||||
height={height - 3}
|
height={height - 3}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col>
|
||||||
<Display maxHeight={height - 3}>
|
<Display maxHeight={height - 3}>
|
||||||
<SquiggleChart
|
<SquiggleChart
|
||||||
squiggleString={squiggleString}
|
squiggleString={squiggleString}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
export { SquiggleChart } from "./components/SquiggleChart";
|
export { SquiggleChart } from "./components/SquiggleChart";
|
||||||
export {
|
export {
|
||||||
SquiggleEditor,
|
SquiggleEditor,
|
||||||
|
SquigglePartial,
|
||||||
renderSquiggleEditorToDom,
|
renderSquiggleEditorToDom,
|
||||||
|
renderSquigglePartialToDom,
|
||||||
} from "./components/SquiggleEditor";
|
} from "./components/SquiggleEditor";
|
||||||
import SquigglePlayground, {
|
import SquigglePlayground, {
|
||||||
renderSquigglePlaygroundToDom,
|
renderSquigglePlaygroundToDom,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
"description": "A basic area chart example",
|
"description": "A basic area chart example",
|
||||||
"width": 500,
|
"width": 500,
|
||||||
"height": 100,
|
"height": 100,
|
||||||
|
"autosize": "fit",
|
||||||
"padding": 5,
|
"padding": 5,
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,6 @@ node_modules
|
||||||
shell.nix
|
shell.nix
|
||||||
.cache
|
.cache
|
||||||
.direnv
|
.direnv
|
||||||
src
|
|
||||||
__tests__
|
__tests__
|
||||||
lib
|
lib
|
||||||
examples
|
examples
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
[![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-lang.svg)](https://www.npmjs.com/package/@quri/squiggle-lang)
|
||||||
|
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/quantified-uncertainty/squiggle/blob/develop/LICENSE)
|
||||||
|
|
||||||
# Squiggle language
|
# Squiggle language
|
||||||
|
|
||||||
## Build for development
|
## Build for development
|
||||||
|
@ -15,13 +18,16 @@ Other:
|
||||||
```sh
|
```sh
|
||||||
yarn start # listens to files and recompiles at every mutation
|
yarn start # listens to files and recompiles at every mutation
|
||||||
yarn test
|
yarn test
|
||||||
yarn test:watch # keeps an active session and runs all tests at every mutation
|
|
||||||
|
|
||||||
# where o := open in osx and o := xdg-open in linux,
|
# where o := open in osx and o := xdg-open in linux,
|
||||||
yarn coverage; o _coverage/index.html # produces coverage report and opens it in browser
|
yarn coverage:rescript; o _coverage/index.html # produces coverage report and opens it in browser
|
||||||
```
|
```
|
||||||
|
|
||||||
## Information
|
## 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.
|
||||||
|
|
||||||
|
# Information
|
||||||
|
|
||||||
Squiggle is a language for representing probability distributions, as well as functions that return probability distributions. Its original intended use is for improving epistemics around EA decisions.
|
Squiggle is a language for representing probability distributions, as well as functions that return probability distributions. Its original intended use is for improving epistemics around EA decisions.
|
||||||
|
|
||||||
|
@ -34,11 +40,3 @@ This package is mainly written in [ReScript](https://rescript-lang.org/), but ha
|
||||||
ReScript has an interesting philosophy of not providing much in the way of effective build tools. Every ReScript file is compiled into `.bs.js` and `.gen.ts` files with the same name and same location, and then you can use these files in other `.js` files to create your program. To generate these files to build the package, you run `yarn build`.
|
ReScript has an interesting philosophy of not providing much in the way of effective build tools. Every ReScript file is compiled into `.bs.js` and `.gen.ts` files with the same name and same location, and then you can use these files in other `.js` files to create your program. To generate these files to build the package, you run `yarn build`.
|
||||||
|
|
||||||
`.gen.ts` files are created by the [`@genType`](https://rescript-lang.org/docs/gentype/latest/getting-started) decorator, which creates typescript typings for needed parts of the codebase so that they can be easily used in typescript. These .gen.ts files reference the .bs.js files generated by rescript.
|
`.gen.ts` files are created by the [`@genType`](https://rescript-lang.org/docs/gentype/latest/getting-started) decorator, which creates typescript typings for needed parts of the codebase so that they can be easily used in typescript. These .gen.ts files reference the .bs.js files generated by rescript.
|
||||||
|
|
||||||
### Errors regarding the `rationale` package
|
|
||||||
|
|
||||||
You may notice sometimes, that there are errors about the `rationale` package. If you ever get these errors, `yarn build` should fix this issue. These errors occur because `yarn build` also needs to create build files that are in `node_modules`. So if you replace `node_modules` you may need to rebuild to get those files back.
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
open Jest
|
|
||||||
open TestHelpers
|
|
||||||
|
|
||||||
describe("Continuous and discrete splits", () => {
|
|
||||||
makeTest(
|
|
||||||
"splits (1)",
|
|
||||||
SampleSetDist_ToPointSet.Internals.T.splitContinuousAndDiscrete([1.432, 1.33455, 2.0]),
|
|
||||||
([1.432, 1.33455, 2.0], E.FloatFloatMap.empty()),
|
|
||||||
)
|
|
||||||
makeTest(
|
|
||||||
"splits (2)",
|
|
||||||
SampleSetDist_ToPointSet.Internals.T.splitContinuousAndDiscrete([
|
|
||||||
1.432,
|
|
||||||
1.33455,
|
|
||||||
2.0,
|
|
||||||
2.0,
|
|
||||||
2.0,
|
|
||||||
2.0,
|
|
||||||
]) |> (((c, disc)) => (c, disc |> E.FloatFloatMap.toArray)),
|
|
||||||
([1.432, 1.33455], [(2.0, 4.0)]),
|
|
||||||
)
|
|
||||||
|
|
||||||
let makeDuplicatedArray = count => {
|
|
||||||
let arr = Belt.Array.range(1, count) |> E.A.fmap(float_of_int)
|
|
||||||
let sorted = arr |> Belt.SortArray.stableSortBy(_, compare)
|
|
||||||
E.A.concatMany([sorted, sorted, sorted, sorted]) |> Belt.SortArray.stableSortBy(_, compare)
|
|
||||||
}
|
|
||||||
|
|
||||||
let (_, discrete1) = SampleSetDist_ToPointSet.Internals.T.splitContinuousAndDiscrete(
|
|
||||||
makeDuplicatedArray(10),
|
|
||||||
)
|
|
||||||
let toArr1 = discrete1 |> E.FloatFloatMap.toArray
|
|
||||||
makeTest("splitMedium at count=10", toArr1 |> Belt.Array.length, 10)
|
|
||||||
|
|
||||||
let (_c, discrete2) = SampleSetDist_ToPointSet.Internals.T.splitContinuousAndDiscrete(
|
|
||||||
makeDuplicatedArray(500),
|
|
||||||
)
|
|
||||||
let toArr2 = discrete2 |> E.FloatFloatMap.toArray
|
|
||||||
makeTest("splitMedium at count=500", toArr2 |> Belt.Array.length, 500)
|
|
||||||
// makeTest("foo", [] |> Belt.Array.length, 500)
|
|
||||||
})
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
open Jest
|
||||||
|
open TestHelpers
|
||||||
|
|
||||||
|
let prepareInputs = (ar, minWeight) =>
|
||||||
|
E.A.Floats.Sorted.splitContinuousAndDiscreteForMinWeight(ar, ~minDiscreteWeight=minWeight) |> (
|
||||||
|
((c, disc)) => (c, disc |> E.FloatFloatMap.toArray)
|
||||||
|
)
|
||||||
|
|
||||||
|
describe("Continuous and discrete splits", () => {
|
||||||
|
makeTest(
|
||||||
|
"is empty, with no common elements",
|
||||||
|
prepareInputs([1.432, 1.33455, 2.0], 2),
|
||||||
|
([1.33455, 1.432, 2.0], []),
|
||||||
|
)
|
||||||
|
|
||||||
|
makeTest(
|
||||||
|
"only stores 3.5 as discrete when minWeight is 3",
|
||||||
|
prepareInputs([1.432, 1.33455, 2.0, 2.0, 3.5, 3.5, 3.5], 3),
|
||||||
|
([1.33455, 1.432, 2.0, 2.0], [(3.5, 3.0)]),
|
||||||
|
)
|
||||||
|
|
||||||
|
makeTest(
|
||||||
|
"doesn't store 3.5 as discrete when minWeight is 5",
|
||||||
|
prepareInputs([1.432, 1.33455, 2.0, 2.0, 3.5, 3.5, 3.5], 5),
|
||||||
|
([1.33455, 1.432, 2.0, 2.0, 3.5, 3.5, 3.5], []),
|
||||||
|
)
|
||||||
|
|
||||||
|
let makeDuplicatedArray = count => {
|
||||||
|
let arr = Belt.Array.range(1, count) |> E.A.fmap(float_of_int)
|
||||||
|
let sorted = arr |> Belt.SortArray.stableSortBy(_, compare)
|
||||||
|
E.A.concatMany([sorted, sorted, sorted, sorted]) |> Belt.SortArray.stableSortBy(_, compare)
|
||||||
|
}
|
||||||
|
|
||||||
|
let (_, discrete1) = E.A.Floats.Sorted.splitContinuousAndDiscreteForMinWeight(
|
||||||
|
makeDuplicatedArray(10),
|
||||||
|
~minDiscreteWeight=2,
|
||||||
|
)
|
||||||
|
let toArr1 = discrete1 |> E.FloatFloatMap.toArray
|
||||||
|
makeTest("splitMedium at count=10", toArr1 |> Belt.Array.length, 10)
|
||||||
|
|
||||||
|
let (_c, discrete2) = E.A.Floats.Sorted.splitContinuousAndDiscreteForMinWeight(
|
||||||
|
makeDuplicatedArray(500),
|
||||||
|
~minDiscreteWeight=2,
|
||||||
|
)
|
||||||
|
let toArr2 = discrete2 |> E.FloatFloatMap.toArray
|
||||||
|
makeTest("splitMedium at count=500", toArr2 |> Belt.Array.length, 500)
|
||||||
|
// makeTest("foo", [] |> Belt.Array.length, 500)
|
||||||
|
})
|
|
@ -92,11 +92,11 @@ describe("eval on distribution functions", () => {
|
||||||
testEval("log(2, uniform(5,8))", "Ok(Sample Set Distribution)")
|
testEval("log(2, uniform(5,8))", "Ok(Sample Set Distribution)")
|
||||||
testEval(
|
testEval(
|
||||||
"log(normal(5,2), 3)",
|
"log(normal(5,2), 3)",
|
||||||
"Error(Distribution Math Error: Logarithm of input error: First input must completely greater than 0)",
|
"Error(Distribution Math Error: Logarithm of input error: First input must be completely greater than 0)",
|
||||||
)
|
)
|
||||||
testEval(
|
testEval(
|
||||||
"log(normal(5,2), normal(10,1))",
|
"log(normal(5,2), normal(10,1))",
|
||||||
"Error(Distribution Math Error: Logarithm of input error: First input must completely greater than 0)",
|
"Error(Distribution Math Error: Logarithm of input error: First input must be completely greater than 0)",
|
||||||
)
|
)
|
||||||
testEval("log(uniform(5,8))", "Ok(Sample Set Distribution)")
|
testEval("log(uniform(5,8))", "Ok(Sample Set Distribution)")
|
||||||
testEval("log10(uniform(5,8))", "Ok(Sample Set Distribution)")
|
testEval("log10(uniform(5,8))", "Ok(Sample Set Distribution)")
|
||||||
|
|
|
@ -1,23 +1,5 @@
|
||||||
import {
|
import { Distribution, resultMap } from "../../src/js/index";
|
||||||
run,
|
import { testRun, testRunPartial } from "./TestHelpers";
|
||||||
Distribution,
|
|
||||||
resultMap,
|
|
||||||
squiggleExpression,
|
|
||||||
errorValueToString,
|
|
||||||
} from "../../src/js/index";
|
|
||||||
|
|
||||||
let testRun = (x: string): squiggleExpression => {
|
|
||||||
let result = run(x, { sampleCount: 100, xyPointLength: 100 });
|
|
||||||
expect(result.tag).toEqual("Ok");
|
|
||||||
if (result.tag === "Ok") {
|
|
||||||
return result.value;
|
|
||||||
} else {
|
|
||||||
throw Error(
|
|
||||||
"Expected squiggle expression to evaluate but got error: " +
|
|
||||||
errorValueToString(result.value)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function Ok<b>(x: b) {
|
function Ok<b>(x: b) {
|
||||||
return { tag: "Ok", value: x };
|
return { tag: "Ok", value: x };
|
||||||
|
@ -42,6 +24,50 @@ describe("Log function", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("Array", () => {
|
||||||
|
test("nested Array", () => {
|
||||||
|
expect(testRun("[[1]]")).toEqual({
|
||||||
|
tag: "array",
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
tag: "array",
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
tag: "number",
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Record", () => {
|
||||||
|
test("Return record", () => {
|
||||||
|
expect(testRun("{a: 1}")).toEqual({
|
||||||
|
tag: "record",
|
||||||
|
value: {
|
||||||
|
a: {
|
||||||
|
tag: "number",
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Partials", () => {
|
||||||
|
test("Can pass variables between partials and cells", () => {
|
||||||
|
let bindings = testRunPartial(`x = 5`);
|
||||||
|
let bindings2 = testRunPartial(`y = x + 2`, bindings);
|
||||||
|
expect(testRun(`y + 3`, bindings2)).toEqual({
|
||||||
|
tag: "number",
|
||||||
|
value: 10,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("Distribution", () => {
|
describe("Distribution", () => {
|
||||||
//It's important that sampleCount is less than 9. If it's more, than that will create randomness
|
//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.
|
//Also, note, the value should be created using makeSampleSetDist() later on.
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import {
|
import {
|
||||||
run,
|
run,
|
||||||
// Distribution,
|
runPartial,
|
||||||
|
bindings,
|
||||||
squiggleExpression,
|
squiggleExpression,
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
// errorValue,
|
|
||||||
// result,
|
|
||||||
} from "../../src/js/index";
|
} from "../../src/js/index";
|
||||||
|
|
||||||
export function testRun(x: string): squiggleExpression {
|
export function testRun(x: string, bindings = {}): squiggleExpression {
|
||||||
let squiggleResult = run(x, { sampleCount: 1000, xyPointLength: 100 });
|
let squiggleResult = run(x, bindings, {
|
||||||
|
sampleCount: 1000,
|
||||||
|
xyPointLength: 100,
|
||||||
|
});
|
||||||
// return squiggleResult.value
|
// return squiggleResult.value
|
||||||
if (squiggleResult.tag === "Ok") {
|
if (squiggleResult.tag === "Ok") {
|
||||||
return squiggleResult.value;
|
return squiggleResult.value;
|
||||||
|
@ -21,6 +23,22 @@ export function testRun(x: string): squiggleExpression {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function testRunPartial(x: string, bindings: bindings = {}): bindings {
|
||||||
|
let squiggleResult = runPartial(x, bindings, {
|
||||||
|
sampleCount: 1000,
|
||||||
|
xyPointLength: 100,
|
||||||
|
});
|
||||||
|
if (squiggleResult.tag === "Ok") {
|
||||||
|
return squiggleResult.value;
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`Expected squiggle expression to evaluate but got error: ${errorValueToString(
|
||||||
|
squiggleResult.value
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function failDefault() {
|
export function failDefault() {
|
||||||
expect("be reached").toBe("codepath should never");
|
expect("be reached").toBe("codepath should never");
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,26 @@ let pointSetDist3: PointSetTypes.xyShape = {
|
||||||
ys: [0.2, 0.5, 0.8],
|
ys: [0.2, 0.5, 0.8],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let makeAndGetErrorString = (~xs, ~ys) =>
|
||||||
|
XYShape.T.make(~xs, ~ys)->E.R.getError->E.O2.fmap(XYShape.Error.toString)
|
||||||
|
|
||||||
describe("XYShapes", () => {
|
describe("XYShapes", () => {
|
||||||
|
describe("Validator", () => {
|
||||||
|
makeTest(
|
||||||
|
"with no errors",
|
||||||
|
makeAndGetErrorString(~xs=[1.0, 4.0, 8.0], ~ys=[0.2, 0.4, 0.8]),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
makeTest("when empty", makeAndGetErrorString(~xs=[], ~ys=[]), Some("Xs is empty"))
|
||||||
|
makeTest(
|
||||||
|
"when not sorted, different lengths, and not finite",
|
||||||
|
makeAndGetErrorString(~xs=[2.0, 1.0, infinity, 0.0], ~ys=[3.0, Js.Float._NaN]),
|
||||||
|
Some(
|
||||||
|
"Multiple Errors: [Xs is not sorted], [Xs and Ys have different lengths. Xs has length 4 and Ys has length 2], [Xs is not finite. Example value: Infinity], [Ys is not finite. Example value: NaN]",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
describe("logScorePoint", () => {
|
describe("logScorePoint", () => {
|
||||||
makeTest("When identical", XYShape.logScorePoint(30, pointSetDist1, pointSetDist1), Some(0.0))
|
makeTest("When identical", XYShape.logScorePoint(30, pointSetDist1, pointSetDist1), Some(0.0))
|
||||||
makeTest(
|
makeTest(
|
||||||
|
@ -32,16 +51,6 @@ describe("XYShapes", () => {
|
||||||
Some(210.3721280423322),
|
Some(210.3721280423322),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
// describe("transverse", () => {
|
|
||||||
// makeTest(
|
|
||||||
// "When very different",
|
|
||||||
// XYShape.Transversal._transverse(
|
|
||||||
// (aCurrent, aLast) => aCurrent +. aLast,
|
|
||||||
// [|1.0, 2.0, 3.0, 4.0|],
|
|
||||||
// ),
|
|
||||||
// [|1.0, 3.0, 6.0, 10.0|],
|
|
||||||
// )
|
|
||||||
// });
|
|
||||||
describe("integrateWithTriangles", () =>
|
describe("integrateWithTriangles", () =>
|
||||||
makeTest(
|
makeTest(
|
||||||
"integrates correctly",
|
"integrates correctly",
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
],
|
],
|
||||||
"suffix": ".bs.js",
|
"suffix": ".bs.js",
|
||||||
"namespace": true,
|
"namespace": true,
|
||||||
"bs-dependencies": ["@glennsl/rescript-jest", "rationale", "bisect_ppx"],
|
"bs-dependencies": ["@glennsl/rescript-jest", "bisect_ppx"],
|
||||||
"gentypeconfig": {
|
"gentypeconfig": {
|
||||||
"language": "typescript",
|
"language": "typescript",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "@quri/squiggle-lang",
|
"name": "@quri/squiggle-lang",
|
||||||
"version": "0.2.5",
|
"version": "0.2.7",
|
||||||
"homepage": "https://squiggle-language.com",
|
"homepage": "https://squiggle-language.com",
|
||||||
"licence": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rescript build -with-deps",
|
"build": "rescript build -with-deps && tsc",
|
||||||
"bundle": "webpack",
|
"bundle": "webpack",
|
||||||
"start": "rescript build -w -with-deps",
|
"start": "rescript build -w -with-deps",
|
||||||
"clean": "rescript clean",
|
"clean": "rescript clean && rm -r dist",
|
||||||
"test:reducer": "jest __tests__/Reducer*/",
|
"test:reducer": "jest __tests__/Reducer*/",
|
||||||
"benchmark": "ts-node benchmark/conversion_tests.ts",
|
"benchmark": "ts-node benchmark/conversion_tests.ts",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
|
@ -31,34 +31,28 @@
|
||||||
],
|
],
|
||||||
"author": "Quantified Uncertainty Research Institute",
|
"author": "Quantified Uncertainty Research Institute",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"rescript": "^9.1.4",
|
||||||
|
"jstat": "^1.9.5",
|
||||||
|
"pdfast": "^0.2.0",
|
||||||
|
"mathjs": "10.5.0"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bisect_ppx": "^2.7.1",
|
"bisect_ppx": "^2.7.1",
|
||||||
"jstat": "^1.9.5",
|
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"mathjs": "10.5.0",
|
|
||||||
"pdfast": "^0.2.0",
|
|
||||||
"rationale": "0.2.0",
|
|
||||||
"rescript": "^9.1.4",
|
|
||||||
"rescript-fast-check": "^1.1.1",
|
"rescript-fast-check": "^1.1.1",
|
||||||
"@glennsl/rescript-jest": "^0.9.0",
|
"@glennsl/rescript-jest": "^0.9.0",
|
||||||
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
||||||
"@types/jest": "^27.4.0",
|
"@types/jest": "^27.4.0",
|
||||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
|
||||||
"bisect_ppx": "^2.7.1",
|
"chalk": "^5.0.1",
|
||||||
"chalk": "^4.1.2",
|
|
||||||
"codecov": "3.8.3",
|
"codecov": "3.8.3",
|
||||||
"fast-check": "2.25.0",
|
"fast-check": "2.25.0",
|
||||||
"gentype": "^4.3.0",
|
"gentype": "^4.3.0",
|
||||||
"jest": "^27.5.1",
|
"jest": "^27.5.1",
|
||||||
"jstat": "^1.9.5",
|
|
||||||
"lodash": "4.17.21",
|
|
||||||
"mathjs": "10.5.0",
|
|
||||||
"moduleserve": "0.9.1",
|
"moduleserve": "0.9.1",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"pdfast": "^0.2.0",
|
|
||||||
"rationale": "0.2.0",
|
|
||||||
"reanalyze": "^2.19.0",
|
"reanalyze": "^2.19.0",
|
||||||
"rescript": "^9.1.4",
|
|
||||||
"ts-jest": "^27.1.4",
|
"ts-jest": "^27.1.4",
|
||||||
"ts-loader": "^9.2.8",
|
"ts-loader": "^9.2.8",
|
||||||
"ts-node": "^10.7.0",
|
"ts-node": "^10.7.0",
|
||||||
|
@ -67,6 +61,6 @@
|
||||||
"webpack-cli": "^4.9.2"
|
"webpack-cli": "^4.9.2"
|
||||||
},
|
},
|
||||||
"source": "./src/js/index.ts",
|
"source": "./src/js/index.ts",
|
||||||
"main": "./dist/bundle.js",
|
"main": "./dist/src/js/index.js",
|
||||||
"types": "./dist/js/index.d.ts"
|
"types": "./dist/src/js/index.d.ts"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,9 @@ import * as _ from "lodash";
|
||||||
import {
|
import {
|
||||||
genericDist,
|
genericDist,
|
||||||
samplingParams,
|
samplingParams,
|
||||||
evaluate,
|
evaluateUsingExternalBindings,
|
||||||
|
evaluatePartialUsingExternalBindings,
|
||||||
|
externalBindings,
|
||||||
expressionValue,
|
expressionValue,
|
||||||
errorValue,
|
errorValue,
|
||||||
distributionError,
|
distributionError,
|
||||||
|
@ -10,6 +12,9 @@ import {
|
||||||
continuousShape,
|
continuousShape,
|
||||||
discreteShape,
|
discreteShape,
|
||||||
distributionErrorToString,
|
distributionErrorToString,
|
||||||
|
mixedShape,
|
||||||
|
sampleSetDist,
|
||||||
|
symbolicDist,
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
export {
|
export {
|
||||||
makeSampleSetDist,
|
makeSampleSetDist,
|
||||||
|
@ -43,7 +48,7 @@ import {
|
||||||
Constructors_pointwiseLogarithm,
|
Constructors_pointwiseLogarithm,
|
||||||
Constructors_pointwisePower,
|
Constructors_pointwisePower,
|
||||||
} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
|
} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
|
||||||
export type { samplingParams, errorValue };
|
export type { samplingParams, errorValue, externalBindings as bindings };
|
||||||
|
|
||||||
export let defaultSamplingInputs: samplingParams = {
|
export let defaultSamplingInputs: samplingParams = {
|
||||||
sampleCount: 10000,
|
sampleCount: 10000,
|
||||||
|
@ -90,26 +95,67 @@ export type squiggleExpression =
|
||||||
| tagged<"distribution", Distribution>
|
| tagged<"distribution", Distribution>
|
||||||
| tagged<"number", number>
|
| tagged<"number", number>
|
||||||
| tagged<"record", { [key: string]: squiggleExpression }>;
|
| tagged<"record", { [key: string]: squiggleExpression }>;
|
||||||
|
|
||||||
export function run(
|
export function run(
|
||||||
squiggleString: string,
|
squiggleString: string,
|
||||||
|
bindings?: externalBindings,
|
||||||
samplingInputs?: samplingParams
|
samplingInputs?: samplingParams
|
||||||
): result<squiggleExpression, errorValue> {
|
): result<squiggleExpression, errorValue> {
|
||||||
|
let b = bindings ? bindings : {};
|
||||||
let si: samplingParams = samplingInputs
|
let si: samplingParams = samplingInputs
|
||||||
? samplingInputs
|
? samplingInputs
|
||||||
: defaultSamplingInputs;
|
: defaultSamplingInputs;
|
||||||
let result: result<expressionValue, errorValue> = evaluate(squiggleString);
|
|
||||||
|
let result: result<expressionValue, errorValue> =
|
||||||
|
evaluateUsingExternalBindings(squiggleString, b);
|
||||||
return resultMap(result, (x) => createTsExport(x, si));
|
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
|
||||||
|
): result<externalBindings, errorValue> {
|
||||||
|
return evaluatePartialUsingExternalBindings(squiggleString, bindings);
|
||||||
|
}
|
||||||
|
|
||||||
function createTsExport(
|
function createTsExport(
|
||||||
x: expressionValue,
|
x: expressionValue,
|
||||||
sampEnv: samplingParams
|
sampEnv: samplingParams
|
||||||
): squiggleExpression {
|
): squiggleExpression {
|
||||||
switch (x.tag) {
|
switch (x.tag) {
|
||||||
case "EvArray":
|
case "EvArray":
|
||||||
|
// genType doesn't convert anything more than 2 layers down into {tag: x, value: x}
|
||||||
|
// format, leaving it as the raw values. This converts the raw values
|
||||||
|
// directly into typescript values.
|
||||||
|
//
|
||||||
|
// The casting here is because genType is about the types of the returned
|
||||||
|
// values, claiming they are fully recursive when that's not actually the
|
||||||
|
// case
|
||||||
return tag(
|
return tag(
|
||||||
"array",
|
"array",
|
||||||
x.value.map((x) => createTsExport(x, sampEnv))
|
x.value.map((arrayItem): squiggleExpression => {
|
||||||
|
switch (arrayItem.tag) {
|
||||||
|
case "EvRecord":
|
||||||
|
return tag(
|
||||||
|
"record",
|
||||||
|
_.mapValues(arrayItem.value, (recordValue: unknown) =>
|
||||||
|
convertRawToTypescript(recordValue as rescriptExport, sampEnv)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
case "EvArray":
|
||||||
|
let y = arrayItem.value as unknown as rescriptExport[];
|
||||||
|
return tag(
|
||||||
|
"array",
|
||||||
|
y.map((childArrayItem) =>
|
||||||
|
convertRawToTypescript(childArrayItem, sampEnv)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return createTsExport(arrayItem, sampEnv);
|
||||||
|
}
|
||||||
|
})
|
||||||
);
|
);
|
||||||
case "EvBool":
|
case "EvBool":
|
||||||
return tag("boolean", x.value);
|
return tag("boolean", x.value);
|
||||||
|
@ -120,10 +166,14 @@ function createTsExport(
|
||||||
case "EvNumber":
|
case "EvNumber":
|
||||||
return tag("number", x.value);
|
return tag("number", x.value);
|
||||||
case "EvRecord":
|
case "EvRecord":
|
||||||
return tag(
|
// genType doesn't support records, so we have to do the raw conversion ourself
|
||||||
|
let result: tagged<"record", { [key: string]: squiggleExpression }> = tag(
|
||||||
"record",
|
"record",
|
||||||
_.mapValues(x.value, (x) => createTsExport(x, sampEnv))
|
_.mapValues(x.value, (x: unknown) =>
|
||||||
|
convertRawToTypescript(x as rescriptExport, sampEnv)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
return result;
|
||||||
case "EvString":
|
case "EvString":
|
||||||
return tag("string", x.value);
|
return tag("string", x.value);
|
||||||
case "EvSymbol":
|
case "EvSymbol":
|
||||||
|
@ -131,6 +181,118 @@ function createTsExport(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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<a, c>(r: result<a, c>): a | c {
|
export function resultExn<a, c>(r: result<a, c>): a | c {
|
||||||
return r.value;
|
return r.value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ type error =
|
||||||
| RequestedStrategyInvalidError(string)
|
| RequestedStrategyInvalidError(string)
|
||||||
| LogarithmOfDistributionError(string)
|
| LogarithmOfDistributionError(string)
|
||||||
| OtherError(string)
|
| OtherError(string)
|
||||||
|
| XYShapeError(XYShape.error)
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
module Error = {
|
module Error = {
|
||||||
|
@ -39,6 +40,7 @@ module Error = {
|
||||||
| PointSetConversionError(err) => SampleSetDist.pointsetConversionErrorToString(err)
|
| PointSetConversionError(err) => SampleSetDist.pointsetConversionErrorToString(err)
|
||||||
| SparklineError(err) => PointSetTypes.sparklineErrorToString(err)
|
| SparklineError(err) => PointSetTypes.sparklineErrorToString(err)
|
||||||
| RequestedStrategyInvalidError(err) => `Requested strategy invalid: ${err}`
|
| RequestedStrategyInvalidError(err) => `Requested strategy invalid: ${err}`
|
||||||
|
| XYShapeError(err) => `XY Shape Error: ${XYShape.Error.toString(err)}`
|
||||||
| OtherError(s) => s
|
| OtherError(s) => s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,24 @@ type toSampleSetFn = t => result<SampleSetDist.t, error>
|
||||||
type scaleMultiplyFn = (t, float) => result<t, error>
|
type scaleMultiplyFn = (t, float) => result<t, error>
|
||||||
type pointwiseAddFn = (t, t) => result<t, error>
|
type pointwiseAddFn = (t, t) => result<t, error>
|
||||||
|
|
||||||
|
let isPointSet = (t: t) =>
|
||||||
|
switch t {
|
||||||
|
| PointSet(_) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
let isSampleSetSet = (t: t) =>
|
||||||
|
switch t {
|
||||||
|
| SampleSet(_) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
let isSymbolic = (t: t) =>
|
||||||
|
switch t {
|
||||||
|
| Symbolic(_) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
|
||||||
let sampleN = (t: t, n) =>
|
let sampleN = (t: t, n) =>
|
||||||
switch t {
|
switch t {
|
||||||
| PointSet(r) => PointSetDist.sampleNRendered(n, r)
|
| PointSet(r) => PointSetDist.sampleNRendered(n, r)
|
||||||
|
@ -150,144 +168,147 @@ let truncate = Truncate.run
|
||||||
of a new variable that is the result of the operation on A and B.
|
of a new variable that is the result of the operation on A and B.
|
||||||
For instance, normal(0, 1) + normal(1, 1) -> normal(1, 2).
|
For instance, normal(0, 1) + normal(1, 1) -> normal(1, 2).
|
||||||
In general, this is implemented via convolution.
|
In general, this is implemented via convolution.
|
||||||
|
|
||||||
TODO: It would be useful to be able to pass in a paramater to get this to run either with convolution or monte carlo.
|
|
||||||
*/
|
*/
|
||||||
module AlgebraicCombination = {
|
module AlgebraicCombination = {
|
||||||
let runConvolution = (
|
module InputValidator = {
|
||||||
toPointSet: toPointSetFn,
|
/*
|
||||||
arithmeticOperation: Operation.convolutionOperation,
|
|
||||||
t1: t,
|
|
||||||
t2: t,
|
|
||||||
) =>
|
|
||||||
E.R.merge(toPointSet(t1), toPointSet(t2))->E.R2.fmap(((a, b)) =>
|
|
||||||
PointSetDist.combineAlgebraically(arithmeticOperation, a, b)
|
|
||||||
)
|
|
||||||
|
|
||||||
let runMonteCarlo = (
|
|
||||||
toSampleSet: toSampleSetFn,
|
|
||||||
arithmeticOperation: Operation.algebraicOperation,
|
|
||||||
t1: t,
|
|
||||||
t2: t,
|
|
||||||
): result<t, error> => {
|
|
||||||
let fn = Operation.Algebraic.toFn(arithmeticOperation)
|
|
||||||
E.R.merge(toSampleSet(t1), toSampleSet(t2))
|
|
||||||
->E.R.bind(((t1, t2)) => {
|
|
||||||
SampleSetDist.map2(~fn, ~t1, ~t2)->E.R2.errMap(x => DistributionTypes.OperationError(x))
|
|
||||||
})
|
|
||||||
->E.R2.fmap(r => DistributionTypes.SampleSet(r))
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
It would be good to also do a check to make sure that probability mass for the second
|
It would be good to also do a check to make sure that probability mass for the second
|
||||||
operand, at value 1.0, is 0 (or approximately 0). However, we'd ideally want to check
|
operand, at value 1.0, is 0 (or approximately 0). However, we'd ideally want to check
|
||||||
that both the probability mass and the probability density are greater than zero.
|
that both the probability mass and the probability density are greater than zero.
|
||||||
Right now we don't yet have a way of getting probability mass, so I'll leave this for later.
|
Right now we don't yet have a way of getting probability mass, so I'll leave this for later.
|
||||||
*/
|
*/
|
||||||
let getLogarithmInputError = (t1: t, t2: t, ~toPointSetFn: toPointSetFn): option<error> => {
|
let getLogarithmInputError = (t1: t, t2: t, ~toPointSetFn: toPointSetFn): option<error> => {
|
||||||
let firstOperandIsGreaterThanZero =
|
let firstOperandIsGreaterThanZero =
|
||||||
toFloatOperation(
|
toFloatOperation(
|
||||||
t1,
|
t1,
|
||||||
~toPointSetFn,
|
~toPointSetFn,
|
||||||
~distToFloatOperation=#Cdf(MagicNumbers.Epsilon.ten),
|
~distToFloatOperation=#Cdf(MagicNumbers.Epsilon.ten),
|
||||||
) |> E.R.fmap(r => r > 0.)
|
) |> E.R.fmap(r => r > 0.)
|
||||||
let secondOperandIsGreaterThanZero =
|
let secondOperandIsGreaterThanZero =
|
||||||
toFloatOperation(
|
toFloatOperation(
|
||||||
t2,
|
t2,
|
||||||
~toPointSetFn,
|
~toPointSetFn,
|
||||||
~distToFloatOperation=#Cdf(MagicNumbers.Epsilon.ten),
|
~distToFloatOperation=#Cdf(MagicNumbers.Epsilon.ten),
|
||||||
) |> E.R.fmap(r => r > 0.)
|
) |> E.R.fmap(r => r > 0.)
|
||||||
let items = E.A.R.firstErrorOrOpen([
|
let items = E.A.R.firstErrorOrOpen([
|
||||||
firstOperandIsGreaterThanZero,
|
firstOperandIsGreaterThanZero,
|
||||||
secondOperandIsGreaterThanZero,
|
secondOperandIsGreaterThanZero,
|
||||||
])
|
])
|
||||||
switch items {
|
switch items {
|
||||||
| Error(r) => Some(r)
|
| Error(r) => Some(r)
|
||||||
| Ok([true, _]) =>
|
| Ok([true, _]) =>
|
||||||
Some(LogarithmOfDistributionError("First input must completely greater than 0"))
|
Some(LogarithmOfDistributionError("First input must be completely greater than 0"))
|
||||||
| Ok([false, true]) =>
|
| Ok([false, true]) =>
|
||||||
Some(LogarithmOfDistributionError("Second input must completely greater than 0"))
|
Some(LogarithmOfDistributionError("Second input must be completely greater than 0"))
|
||||||
| Ok([false, false]) => None
|
| Ok([false, false]) => None
|
||||||
| Ok(_) => Some(Unreachable)
|
| Ok(_) => Some(Unreachable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let run = (t1: t, t2: t, ~toPointSetFn: toPointSetFn, ~arithmeticOperation): option<error> => {
|
||||||
|
if arithmeticOperation == #Logarithm {
|
||||||
|
getLogarithmInputError(t1, t2, ~toPointSetFn)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let getInvalidOperationError = (
|
module StrategyCallOnValidatedInputs = {
|
||||||
t1: t,
|
let convolution = (
|
||||||
t2: t,
|
toPointSet: toPointSetFn,
|
||||||
~toPointSetFn: toPointSetFn,
|
arithmeticOperation: Operation.convolutionOperation,
|
||||||
|
t1: t,
|
||||||
|
t2: t,
|
||||||
|
): result<t, error> =>
|
||||||
|
E.R.merge(toPointSet(t1), toPointSet(t2))
|
||||||
|
->E.R2.fmap(((a, b)) => PointSetDist.combineAlgebraically(arithmeticOperation, a, b))
|
||||||
|
->E.R2.fmap(r => DistributionTypes.PointSet(r))
|
||||||
|
|
||||||
|
let monteCarlo = (
|
||||||
|
toSampleSet: toSampleSetFn,
|
||||||
|
arithmeticOperation: Operation.algebraicOperation,
|
||||||
|
t1: t,
|
||||||
|
t2: t,
|
||||||
|
): result<t, error> => {
|
||||||
|
let fn = Operation.Algebraic.toFn(arithmeticOperation)
|
||||||
|
E.R.merge(toSampleSet(t1), toSampleSet(t2))
|
||||||
|
->E.R.bind(((t1, t2)) => {
|
||||||
|
SampleSetDist.map2(~fn, ~t1, ~t2)->E.R2.errMap(x => DistributionTypes.OperationError(x))
|
||||||
|
})
|
||||||
|
->E.R2.fmap(r => DistributionTypes.SampleSet(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
let symbolic = (
|
||||||
|
arithmeticOperation: Operation.algebraicOperation,
|
||||||
|
t1: t,
|
||||||
|
t2: t,
|
||||||
|
): SymbolicDistTypes.analyticalSimplificationResult => {
|
||||||
|
switch (t1, t2) {
|
||||||
|
| (DistributionTypes.Symbolic(d1), DistributionTypes.Symbolic(d2)) =>
|
||||||
|
SymbolicDist.T.tryAnalyticalSimplification(d1, d2, arithmeticOperation)
|
||||||
|
| _ => #NoSolution
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module StrategyChooser = {
|
||||||
|
type specificStrategy = [#AsSymbolic | #AsMonteCarlo | #AsConvolution]
|
||||||
|
|
||||||
|
//I'm (Ozzie) really just guessing here, very little idea what's best
|
||||||
|
let expectedConvolutionCost: t => int = x =>
|
||||||
|
switch x {
|
||||||
|
| Symbolic(#Float(_)) => MagicNumbers.OpCost.floatCost
|
||||||
|
| Symbolic(_) => MagicNumbers.OpCost.symbolicCost
|
||||||
|
| PointSet(Discrete(m)) => m.xyShape->XYShape.T.length
|
||||||
|
| PointSet(Mixed(_)) => MagicNumbers.OpCost.mixedCost
|
||||||
|
| PointSet(Continuous(_)) => MagicNumbers.OpCost.continuousCost
|
||||||
|
| _ => MagicNumbers.OpCost.wildcardCost
|
||||||
|
}
|
||||||
|
|
||||||
|
let hasSampleSetDist = (t1: t, t2: t): bool => isSampleSetSet(t1) || isSampleSetSet(t2)
|
||||||
|
|
||||||
|
let convolutionIsFasterThanMonteCarlo = (t1: t, t2: t): bool =>
|
||||||
|
expectedConvolutionCost(t1) * expectedConvolutionCost(t2) < MagicNumbers.OpCost.monteCarloCost
|
||||||
|
|
||||||
|
let preferConvolutionToMonteCarlo = (t1, t2, arithmeticOperation) => {
|
||||||
|
!hasSampleSetDist(t1, t2) &&
|
||||||
|
Operation.Convolution.canDoAlgebraicOperation(arithmeticOperation) &&
|
||||||
|
convolutionIsFasterThanMonteCarlo(t1, t2)
|
||||||
|
}
|
||||||
|
|
||||||
|
let run = (~t1: t, ~t2: t, ~arithmeticOperation): specificStrategy => {
|
||||||
|
switch StrategyCallOnValidatedInputs.symbolic(arithmeticOperation, t1, t2) {
|
||||||
|
| #AnalyticalSolution(_)
|
||||||
|
| #Error(_) =>
|
||||||
|
#AsSymbolic
|
||||||
|
| #NoSolution =>
|
||||||
|
preferConvolutionToMonteCarlo(t1, t2, arithmeticOperation) ? #AsConvolution : #AsMonteCarlo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let runStrategyOnValidatedInputs = (
|
||||||
|
~t1: t,
|
||||||
|
~t2: t,
|
||||||
~arithmeticOperation,
|
~arithmeticOperation,
|
||||||
): option<error> => {
|
~strategy: StrategyChooser.specificStrategy,
|
||||||
if arithmeticOperation == #Logarithm {
|
|
||||||
getLogarithmInputError(t1, t2, ~toPointSetFn)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//I'm (Ozzie) really just guessing here, very little idea what's best
|
|
||||||
let expectedConvolutionCost: t => int = x =>
|
|
||||||
switch x {
|
|
||||||
| Symbolic(#Float(_)) => MagicNumbers.OpCost.floatCost
|
|
||||||
| Symbolic(_) => MagicNumbers.OpCost.symbolicCost
|
|
||||||
| PointSet(Discrete(m)) => m.xyShape->XYShape.T.length
|
|
||||||
| PointSet(Mixed(_)) => MagicNumbers.OpCost.mixedCost
|
|
||||||
| PointSet(Continuous(_)) => MagicNumbers.OpCost.continuousCost
|
|
||||||
| _ => MagicNumbers.OpCost.wildcardCost
|
|
||||||
}
|
|
||||||
|
|
||||||
type calculationStrategy = MonteCarloStrat | ConvolutionStrat(Operation.convolutionOperation)
|
|
||||||
|
|
||||||
let chooseConvolutionOrMonteCarloDefault = (
|
|
||||||
op: Operation.algebraicOperation,
|
|
||||||
t2: t,
|
|
||||||
t1: t,
|
|
||||||
): calculationStrategy =>
|
|
||||||
switch op {
|
|
||||||
| #Divide
|
|
||||||
| #Power
|
|
||||||
| #Logarithm =>
|
|
||||||
MonteCarloStrat
|
|
||||||
| (#Add | #Subtract | #Multiply) as convOp =>
|
|
||||||
expectedConvolutionCost(t1) * expectedConvolutionCost(t2) > MagicNumbers.OpCost.monteCarloCost
|
|
||||||
? MonteCarloStrat
|
|
||||||
: ConvolutionStrat(convOp)
|
|
||||||
}
|
|
||||||
|
|
||||||
let tryAnalyticalSimplification = (
|
|
||||||
arithmeticOperation: Operation.algebraicOperation,
|
|
||||||
t1: t,
|
|
||||||
t2: t,
|
|
||||||
): option<SymbolicDistTypes.analyticalSimplificationResult> => {
|
|
||||||
switch (t1, t2) {
|
|
||||||
| (DistributionTypes.Symbolic(d1), DistributionTypes.Symbolic(d2)) =>
|
|
||||||
Some(SymbolicDist.T.tryAnalyticalSimplification(d1, d2, arithmeticOperation))
|
|
||||||
| _ => None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let runDefault = (
|
|
||||||
t1: t,
|
|
||||||
~toPointSetFn: toPointSetFn,
|
~toPointSetFn: toPointSetFn,
|
||||||
~toSampleSetFn: toSampleSetFn,
|
~toSampleSetFn: toSampleSetFn,
|
||||||
~arithmeticOperation,
|
|
||||||
~t2: t,
|
|
||||||
): result<t, error> => {
|
): result<t, error> => {
|
||||||
switch tryAnalyticalSimplification(arithmeticOperation, t1, t2) {
|
switch strategy {
|
||||||
| Some(#AnalyticalSolution(symbolicDist)) => Ok(Symbolic(symbolicDist))
|
| #AsMonteCarlo =>
|
||||||
| Some(#Error(e)) => Error(OperationError(e))
|
StrategyCallOnValidatedInputs.monteCarlo(toSampleSetFn, arithmeticOperation, t1, t2)
|
||||||
| Some(#NoSolution)
|
| #AsSymbolic =>
|
||||||
| None =>
|
switch StrategyCallOnValidatedInputs.symbolic(arithmeticOperation, t1, t2) {
|
||||||
switch getInvalidOperationError(t1, t2, ~toPointSetFn, ~arithmeticOperation) {
|
| #AnalyticalSolution(symbolicDist) => Ok(Symbolic(symbolicDist))
|
||||||
| Some(e) => Error(e)
|
| #Error(e) => Error(OperationError(e))
|
||||||
| None =>
|
| #NoSolution => Error(Unreachable)
|
||||||
switch chooseConvolutionOrMonteCarloDefault(arithmeticOperation, t1, t2) {
|
}
|
||||||
| MonteCarloStrat => runMonteCarlo(toSampleSetFn, arithmeticOperation, t1, t2)
|
| #AsConvolution =>
|
||||||
| ConvolutionStrat(convOp) =>
|
switch Operation.Convolution.fromAlgebraicOperation(arithmeticOperation) {
|
||||||
runConvolution(toPointSetFn, convOp, t1, t2)->E.R2.fmap(r => DistributionTypes.PointSet(
|
| Some(convOp) => StrategyCallOnValidatedInputs.convolution(toPointSetFn, convOp, t1, t2)
|
||||||
r,
|
| None => Error(Unreachable)
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,27 +321,38 @@ module AlgebraicCombination = {
|
||||||
~arithmeticOperation: Operation.algebraicOperation,
|
~arithmeticOperation: Operation.algebraicOperation,
|
||||||
~t2: t,
|
~t2: t,
|
||||||
): result<t, error> => {
|
): result<t, error> => {
|
||||||
switch strategy {
|
let invalidOperationError = InputValidator.run(t1, t2, ~arithmeticOperation, ~toPointSetFn)
|
||||||
| AsDefault => runDefault(t1, ~toPointSetFn, ~toSampleSetFn, ~arithmeticOperation, ~t2)
|
switch (invalidOperationError, strategy) {
|
||||||
| AsSymbolic =>
|
| (Some(e), _) => Error(e)
|
||||||
switch tryAnalyticalSimplification(arithmeticOperation, t1, t2) {
|
| (None, AsDefault) => {
|
||||||
| Some(#AnalyticalSolution(symbolicDist)) => Ok(Symbolic(symbolicDist))
|
let chooseStrategy = StrategyChooser.run(~arithmeticOperation, ~t1, ~t2)
|
||||||
| Some(#NoSolution) => Error(RequestedStrategyInvalidError(`No analytical solution`))
|
runStrategyOnValidatedInputs(
|
||||||
| None => Error(RequestedStrategyInvalidError("Inputs were not even symbolic"))
|
~t1,
|
||||||
| Some(#Error(err)) => Error(OperationError(err))
|
~t2,
|
||||||
|
~strategy=chooseStrategy,
|
||||||
|
~arithmeticOperation,
|
||||||
|
~toPointSetFn,
|
||||||
|
~toSampleSetFn,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
| AsConvolution => {
|
| (None, AsMonteCarlo) =>
|
||||||
let errString = opString => `Can't convolve on ${opString}`
|
StrategyCallOnValidatedInputs.monteCarlo(toSampleSetFn, arithmeticOperation, t1, t2)
|
||||||
switch arithmeticOperation {
|
| (None, AsSymbolic) =>
|
||||||
| (#Add | #Subtract | #Multiply) as convOp =>
|
switch StrategyCallOnValidatedInputs.symbolic(arithmeticOperation, t1, t2) {
|
||||||
runConvolution(toPointSetFn, convOp, t1, t2)->E.R2.fmap(r => DistributionTypes.PointSet(
|
| #AnalyticalSolution(symbolicDist) => Ok(Symbolic(symbolicDist))
|
||||||
r,
|
| #NoSolution => Error(RequestedStrategyInvalidError(`No analytic solution for inputs`))
|
||||||
))
|
| #Error(err) => Error(OperationError(err))
|
||||||
| (#Divide | #Power | #Logarithm) as op =>
|
}
|
||||||
op->Operation.Algebraic.toString->errString->RequestedStrategyInvalidError->Error
|
| (None, AsConvolution) =>
|
||||||
|
switch Operation.Convolution.fromAlgebraicOperation(arithmeticOperation) {
|
||||||
|
| None => {
|
||||||
|
let errString = `Convolution not supported for ${Operation.Algebraic.toString(
|
||||||
|
arithmeticOperation,
|
||||||
|
)}`
|
||||||
|
Error(RequestedStrategyInvalidError(errString))
|
||||||
}
|
}
|
||||||
|
| Some(convOp) => StrategyCallOnValidatedInputs.convolution(toPointSetFn, convOp, t1, t2)
|
||||||
}
|
}
|
||||||
| AsMonteCarlo => runMonteCarlo(toSampleSetFn, arithmeticOperation, t1, t2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,3 +69,6 @@ let mixture: (
|
||||||
~scaleMultiplyFn: scaleMultiplyFn,
|
~scaleMultiplyFn: scaleMultiplyFn,
|
||||||
~pointwiseAddFn: pointwiseAddFn,
|
~pointwiseAddFn: pointwiseAddFn,
|
||||||
) => result<t, error>
|
) => result<t, error>
|
||||||
|
|
||||||
|
let isSymbolic: t => bool
|
||||||
|
let isPointSet: t => bool
|
||||||
|
|
|
@ -263,4 +263,4 @@ let combineShapesContinuousDiscrete = (
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let isOrdered = (a: XYShape.T.t): bool => E.A.Sorted.Floats.isSorted(a.xs)
|
let isOrdered = (a: XYShape.T.t): bool => E.A.Floats.isSorted(a.xs)
|
||||||
|
|
|
@ -39,28 +39,6 @@ module Internals = {
|
||||||
module T = {
|
module T = {
|
||||||
type t = array<float>
|
type t = array<float>
|
||||||
|
|
||||||
let splitContinuousAndDiscrete = (sortedArray: t) => {
|
|
||||||
let continuous = []
|
|
||||||
let discrete = E.FloatFloatMap.empty()
|
|
||||||
Belt.Array.forEachWithIndex(sortedArray, (index, element) => {
|
|
||||||
let maxIndex = (sortedArray |> Array.length) - 1
|
|
||||||
let possiblySimilarElements = switch index {
|
|
||||||
| 0 => [index + 1]
|
|
||||||
| n if n == maxIndex => [index - 1]
|
|
||||||
| _ => [index - 1, index + 1]
|
|
||||||
} |> Belt.Array.map(_, r => sortedArray[r])
|
|
||||||
let hasSimilarElement = Belt.Array.some(possiblySimilarElements, r => r == element)
|
|
||||||
hasSimilarElement
|
|
||||||
? E.FloatFloatMap.increment(element, discrete)
|
|
||||||
: {
|
|
||||||
let _ = Js.Array.push(element, continuous)
|
|
||||||
}
|
|
||||||
|
|
||||||
()
|
|
||||||
})
|
|
||||||
(continuous, discrete)
|
|
||||||
}
|
|
||||||
|
|
||||||
let xWidthToUnitWidth = (samples, outputXYPoints, xWidth) => {
|
let xWidthToUnitWidth = (samples, outputXYPoints, xWidth) => {
|
||||||
let xyPointRange = E.A.Sorted.range(samples) |> E.O.default(0.0)
|
let xyPointRange = E.A.Sorted.range(samples) |> E.O.default(0.0)
|
||||||
let xyPointWidth = xyPointRange /. float_of_int(outputXYPoints)
|
let xyPointWidth = xyPointRange /. float_of_int(outputXYPoints)
|
||||||
|
@ -85,7 +63,11 @@ let toPointSetDist = (
|
||||||
(),
|
(),
|
||||||
): Internals.Types.outputs => {
|
): Internals.Types.outputs => {
|
||||||
Array.fast_sort(compare, samples)
|
Array.fast_sort(compare, samples)
|
||||||
let (continuousPart, discretePart) = E.A.Sorted.Floats.split(samples)
|
let minDiscreteToKeep = MagicNumbers.ToPointSet.minDiscreteToKeep(samples)
|
||||||
|
let (continuousPart, discretePart) = E.A.Floats.Sorted.splitContinuousAndDiscreteForMinWeight(
|
||||||
|
samples,
|
||||||
|
~minDiscreteWeight=minDiscreteToKeep,
|
||||||
|
)
|
||||||
let length = samples |> E.A.length |> float_of_int
|
let length = samples |> E.A.length |> float_of_int
|
||||||
let discrete: PointSetTypes.discreteShape =
|
let discrete: PointSetTypes.discreteShape =
|
||||||
discretePart
|
discretePart
|
||||||
|
|
|
@ -22,3 +22,16 @@ module OpCost = {
|
||||||
let wildcardCost = 1000
|
let wildcardCost = 1000
|
||||||
let monteCarloCost = Environment.defaultSampleCount
|
let monteCarloCost = Environment.defaultSampleCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module ToPointSet = {
|
||||||
|
/*
|
||||||
|
This function chooses the minimum amount of duplicate samples that need
|
||||||
|
to exist in order for this to be considered discrete. The tricky thing
|
||||||
|
is that there are some operations that create duplicate continuous samples,
|
||||||
|
so we can't guarantee that these only will occur because the fundamental
|
||||||
|
structure is meant to be discrete. I chose this heuristic because I think
|
||||||
|
it would strike a reasonable trade-off, but I’m really unsure what’s
|
||||||
|
best right now.
|
||||||
|
*/
|
||||||
|
let minDiscreteToKeep = samples => max(20, E.A.length(samples) / 50)
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,12 @@ type samplingParams = DistributionOperation.env
|
||||||
@genType
|
@genType
|
||||||
type genericDist = DistributionTypes.genericDist
|
type genericDist = DistributionTypes.genericDist
|
||||||
|
|
||||||
|
@genType
|
||||||
|
type sampleSetDist = SampleSetDist.t
|
||||||
|
|
||||||
|
@genType
|
||||||
|
type symbolicDist = SymbolicDistTypes.symbolicDist
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type distributionError = DistributionTypes.error
|
type distributionError = DistributionTypes.error
|
||||||
|
|
||||||
|
@ -34,6 +40,12 @@ let evaluate = Reducer.evaluate
|
||||||
@genType
|
@genType
|
||||||
let evaluateUsingExternalBindings = Reducer.evaluateUsingExternalBindings
|
let evaluateUsingExternalBindings = Reducer.evaluateUsingExternalBindings
|
||||||
|
|
||||||
|
@genType
|
||||||
|
let evaluatePartialUsingExternalBindings = Reducer.evaluatePartialUsingExternalBindings
|
||||||
|
|
||||||
|
@genType
|
||||||
|
type externalBindings = Reducer.externalBindings
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
type expressionValue = ReducerInterface_ExpressionValue.expressionValue
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
open Rationale.Function.Infix
|
/*
|
||||||
|
Some functions from modules `L`, `O`, and `R` below were copied directly from
|
||||||
|
running `rescript convert -all` on Rationale https://github.com/jonlaing/rationale
|
||||||
|
*/
|
||||||
module FloatFloatMap = {
|
module FloatFloatMap = {
|
||||||
module Id = Belt.Id.MakeComparable({
|
module Id = Belt.Id.MakeComparable({
|
||||||
type t = float
|
type t = float
|
||||||
|
@ -8,7 +11,7 @@ module FloatFloatMap = {
|
||||||
type t = Belt.MutableMap.t<Id.t, float, Id.identity>
|
type t = Belt.MutableMap.t<Id.t, float, Id.identity>
|
||||||
|
|
||||||
let fromArray = (ar: array<(float, float)>) => Belt.MutableMap.fromArray(ar, ~id=module(Id))
|
let fromArray = (ar: array<(float, float)>) => Belt.MutableMap.fromArray(ar, ~id=module(Id))
|
||||||
let toArray = (t: t) => Belt.MutableMap.toArray(t)
|
let toArray = (t: t): array<(float, float)> => Belt.MutableMap.toArray(t)
|
||||||
let empty = () => Belt.MutableMap.make(~id=module(Id))
|
let empty = () => Belt.MutableMap.make(~id=module(Id))
|
||||||
let increment = (el, t: t) =>
|
let increment = (el, t: t) =>
|
||||||
Belt.MutableMap.update(t, el, x =>
|
Belt.MutableMap.update(t, el, x =>
|
||||||
|
@ -20,6 +23,10 @@ module FloatFloatMap = {
|
||||||
|
|
||||||
let get = (el, t: t) => Belt.MutableMap.get(t, el)
|
let get = (el, t: t) => Belt.MutableMap.get(t, el)
|
||||||
let fmap = (fn, t: t) => Belt.MutableMap.map(t, fn)
|
let fmap = (fn, t: t) => Belt.MutableMap.map(t, fn)
|
||||||
|
let partition = (fn, t: t) => {
|
||||||
|
let (match, noMatch) = Belt.Array.partition(toArray(t), fn)
|
||||||
|
(fromArray(match), fromArray(noMatch))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module Int = {
|
module Int = {
|
||||||
|
@ -51,17 +58,59 @@ module O = {
|
||||||
| None => rFn()
|
| None => rFn()
|
||||||
}
|
}
|
||||||
()
|
()
|
||||||
let fmap = Rationale.Option.fmap
|
let fmap = (f: 'a => 'b, x: option<'a>): option<'b> => {
|
||||||
let bind = Rationale.Option.bind
|
switch x {
|
||||||
let default = Rationale.Option.default
|
| None => None
|
||||||
let isSome = Rationale.Option.isSome
|
| Some(x') => Some(f(x'))
|
||||||
let isNone = Rationale.Option.isNone
|
}
|
||||||
let toExn = Rationale.Option.toExn
|
}
|
||||||
let some = Rationale.Option.some
|
let bind = (o, f) =>
|
||||||
let firstSome = Rationale.Option.firstSome
|
switch o {
|
||||||
let toExt = Rationale.Option.toExn // wanna flag this-- looks like a typo but `Rationale.OptiontoExt` doesn't exist.
|
| None => None
|
||||||
let flatApply = (fn, b) => Rationale.Option.apply(fn, Some(b)) |> Rationale.Option.flatten
|
| Some(a) => f(a)
|
||||||
let flatten = Rationale.Option.flatten
|
}
|
||||||
|
let default = (d, o) =>
|
||||||
|
switch o {
|
||||||
|
| None => d
|
||||||
|
| Some(a) => a
|
||||||
|
}
|
||||||
|
let isSome = o =>
|
||||||
|
switch o {
|
||||||
|
| Some(_) => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
let isNone = o =>
|
||||||
|
switch o {
|
||||||
|
| None => true
|
||||||
|
| _ => false
|
||||||
|
}
|
||||||
|
let toExn = (err, o) =>
|
||||||
|
switch o {
|
||||||
|
| None => raise(Failure(err))
|
||||||
|
| Some(a) => a
|
||||||
|
}
|
||||||
|
|
||||||
|
let some = a => Some(a)
|
||||||
|
let firstSome = (a, b) =>
|
||||||
|
switch a {
|
||||||
|
| None => b
|
||||||
|
| _ => a
|
||||||
|
}
|
||||||
|
|
||||||
|
let toExt = toExn
|
||||||
|
|
||||||
|
let flatten = o =>
|
||||||
|
switch o {
|
||||||
|
| None => None
|
||||||
|
| Some(x) => x
|
||||||
|
}
|
||||||
|
|
||||||
|
let apply = (o, a) =>
|
||||||
|
switch o {
|
||||||
|
| Some(f) => bind(a, b => some(f(b)))
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
let flatApply = (fn, b) => apply(fn, Some(b)) |> flatten
|
||||||
|
|
||||||
let toBool = opt =>
|
let toBool = opt =>
|
||||||
switch opt {
|
switch opt {
|
||||||
|
@ -109,6 +158,11 @@ module O2 = {
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
module F = {
|
module F = {
|
||||||
|
let pipe = (f, g, x) => g(f(x))
|
||||||
|
let compose = (f, g, x) => f(g(x))
|
||||||
|
let flip = (f, a, b) => f(b, a)
|
||||||
|
let always = (x, _y) => x
|
||||||
|
|
||||||
let apply = (a, e) => a |> e
|
let apply = (a, e) => a |> e
|
||||||
|
|
||||||
let flatten2Callbacks = (fn1, fn2, fnlast) =>
|
let flatten2Callbacks = (fn1, fn2, fnlast) =>
|
||||||
|
@ -156,10 +210,31 @@ exception Assertion(string)
|
||||||
|
|
||||||
/* R for Result */
|
/* R for Result */
|
||||||
module R = {
|
module R = {
|
||||||
let result = Rationale.Result.result
|
open Belt.Result
|
||||||
|
let result = (okF, errF, r) =>
|
||||||
|
switch r {
|
||||||
|
| Ok(a) => okF(a)
|
||||||
|
| Error(err) => errF(err)
|
||||||
|
}
|
||||||
let id = e => e |> result(U.id, U.id)
|
let id = e => e |> result(U.id, U.id)
|
||||||
let fmap = Rationale.Result.fmap
|
let isOk = Belt.Result.isOk
|
||||||
let bind = Rationale.Result.bind
|
let getError = (r: result<'a, 'b>) =>
|
||||||
|
switch r {
|
||||||
|
| Ok(_) => None
|
||||||
|
| Error(e) => Some(e)
|
||||||
|
}
|
||||||
|
let fmap = (f: 'a => 'b, r: result<'a, 'c>): result<'b, 'c> => {
|
||||||
|
switch r {
|
||||||
|
| Ok(r') => Ok(f(r'))
|
||||||
|
| Error(err) => Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let bind = (r, f) =>
|
||||||
|
switch r {
|
||||||
|
| Ok(a) => f(a)
|
||||||
|
| Error(err) => Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
let toExn = (msg: string, x: result<'a, 'b>): 'a =>
|
let toExn = (msg: string, x: result<'a, 'b>): 'a =>
|
||||||
switch x {
|
switch x {
|
||||||
| Ok(r) => r
|
| Ok(r) => r
|
||||||
|
@ -186,14 +261,17 @@ module R = {
|
||||||
let errorIfCondition = (errorCondition, errorMessage, r) =>
|
let errorIfCondition = (errorCondition, errorMessage, r) =>
|
||||||
errorCondition(r) ? Error(errorMessage) : Ok(r)
|
errorCondition(r) ? Error(errorMessage) : Ok(r)
|
||||||
|
|
||||||
let ap = Rationale.Result.ap
|
let ap = (r, a) =>
|
||||||
|
switch r {
|
||||||
|
| Ok(f) => Ok(f(a))
|
||||||
|
| Error(err) => Error(err)
|
||||||
|
}
|
||||||
let ap' = (r, a) =>
|
let ap' = (r, a) =>
|
||||||
switch r {
|
switch r {
|
||||||
| Ok(f) => fmap(f, a)
|
| Ok(f) => fmap(f, a)
|
||||||
| Error(err) => Error(err)
|
| Error(err) => Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// (a1 -> a2 -> r) -> m a1 -> m a2 -> m r // not in Rationale
|
|
||||||
let liftM2: (('a, 'b) => 'c, result<'a, 'd>, result<'b, 'd>) => result<'c, 'd> = (op, xR, yR) => {
|
let liftM2: (('a, 'b) => 'c, result<'a, 'd>, result<'b, 'd>) => result<'c, 'd> = (op, xR, yR) => {
|
||||||
ap'(fmap(op, xR), yR)
|
ap'(fmap(op, xR), yR)
|
||||||
}
|
}
|
||||||
|
@ -243,7 +321,7 @@ module S = {
|
||||||
}
|
}
|
||||||
|
|
||||||
module J = {
|
module J = {
|
||||||
let toString = \"||>"(Js.Json.decodeString, O.default(""))
|
let toString = F.pipe(Js.Json.decodeString, O.default(""))
|
||||||
let fromString = Js.Json.string
|
let fromString = Js.Json.string
|
||||||
let fromNumber = Js.Json.number
|
let fromNumber = Js.Json.number
|
||||||
|
|
||||||
|
@ -256,7 +334,7 @@ module J = {
|
||||||
|
|
||||||
let toString = (str: option<'a>) =>
|
let toString = (str: option<'a>) =>
|
||||||
switch str {
|
switch str {
|
||||||
| Some(str) => Some(str |> \"||>"(Js.Json.decodeString, O.default("")))
|
| Some(str) => Some(str |> F.pipe(Js.Json.decodeString, O.default("")))
|
||||||
| _ => None
|
| _ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,34 +349,132 @@ module JsDate = {
|
||||||
|
|
||||||
/* List */
|
/* List */
|
||||||
module L = {
|
module L = {
|
||||||
|
module Util = {
|
||||||
|
let eq = (a, b) => a == b
|
||||||
|
}
|
||||||
let fmap = List.map
|
let fmap = List.map
|
||||||
let get = Belt.List.get
|
let get = Belt.List.get
|
||||||
let toArray = Array.of_list
|
let toArray = Array.of_list
|
||||||
let fmapi = List.mapi
|
let fmapi = List.mapi
|
||||||
let concat = List.concat
|
let concat = List.concat
|
||||||
let drop = Rationale.RList.drop
|
let concat' = (xs, ys) => List.append(ys, xs)
|
||||||
let remove = Rationale.RList.remove
|
|
||||||
|
let rec drop = (i, xs) =>
|
||||||
|
switch (i, xs) {
|
||||||
|
| (_, list{}) => list{}
|
||||||
|
| (i, _) if i <= 0 => xs
|
||||||
|
| (i, list{_, ...b}) => drop(i - 1, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
let append = (a, xs) => List.append(xs, list{a})
|
||||||
|
let take = {
|
||||||
|
let rec loop = (i, xs, acc) =>
|
||||||
|
switch (i, xs) {
|
||||||
|
| (i, _) if i <= 0 => acc
|
||||||
|
| (_, list{}) => acc
|
||||||
|
| (i, list{a, ...b}) => loop(i - 1, b, append(a, acc))
|
||||||
|
}
|
||||||
|
(i, xs) => loop(i, xs, list{})
|
||||||
|
}
|
||||||
|
let takeLast = (i, xs) => List.rev(xs) |> take(i) |> List.rev
|
||||||
|
|
||||||
|
let splitAt = (i, xs) => (take(i, xs), takeLast(List.length(xs) - i, xs))
|
||||||
|
let remove = (i, n, xs) => {
|
||||||
|
let (a, b) = splitAt(i, xs)
|
||||||
|
\"@"(a, drop(n, b))
|
||||||
|
}
|
||||||
|
|
||||||
let find = List.find
|
let find = List.find
|
||||||
let filter = List.filter
|
let filter = List.filter
|
||||||
let for_all = List.for_all
|
let for_all = List.for_all
|
||||||
let exists = List.exists
|
let exists = List.exists
|
||||||
let sort = List.sort
|
let sort = List.sort
|
||||||
let length = List.length
|
let length = List.length
|
||||||
let filter_opt = Rationale.RList.filter_opt
|
|
||||||
let uniqBy = Rationale.RList.uniqBy
|
let filter_opt = xs => {
|
||||||
let join = Rationale.RList.join
|
let rec loop = (l, acc) =>
|
||||||
let head = Rationale.RList.head
|
switch l {
|
||||||
let uniq = Rationale.RList.uniq
|
| list{} => acc
|
||||||
|
| list{hd, ...tl} =>
|
||||||
|
switch hd {
|
||||||
|
| None => loop(tl, acc)
|
||||||
|
| Some(x) => loop(tl, list{x, ...acc})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List.rev(loop(xs, list{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
let containsWith = f => List.exists(f)
|
||||||
|
|
||||||
|
let uniqWithBy = (eq, f, xs) =>
|
||||||
|
List.fold_left(
|
||||||
|
((acc, tacc), v) =>
|
||||||
|
containsWith(eq(f(v)), tacc) ? (acc, tacc) : (append(v, acc), append(f(v), tacc)),
|
||||||
|
(list{}, list{}),
|
||||||
|
xs,
|
||||||
|
) |> fst
|
||||||
|
|
||||||
|
let uniqBy = (f, xs) => uniqWithBy(Util.eq, f, xs)
|
||||||
|
let join = j => List.fold_left((acc, v) => String.length(acc) == 0 ? v : acc ++ (j ++ v), "")
|
||||||
|
|
||||||
|
let head = xs =>
|
||||||
|
switch List.hd(xs) {
|
||||||
|
| exception _ => None
|
||||||
|
| a => Some(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
let uniq = xs => uniqBy(x => x, xs)
|
||||||
let flatten = List.flatten
|
let flatten = List.flatten
|
||||||
let last = Rationale.RList.last
|
let last = xs => xs |> List.rev |> head
|
||||||
let append = List.append
|
let append = List.append
|
||||||
let getBy = Belt.List.getBy
|
let getBy = Belt.List.getBy
|
||||||
let dropLast = Rationale.RList.dropLast
|
let dropLast = (i, xs) => take(List.length(xs) - i, xs)
|
||||||
let contains = Rationale.RList.contains
|
let containsWith = f => List.exists(f)
|
||||||
let without = Rationale.RList.without
|
let contains = x => containsWith(Util.eq(x))
|
||||||
let update = Rationale.RList.update
|
|
||||||
|
let reject = pred => List.filter(x => !pred(x))
|
||||||
|
let tail = xs =>
|
||||||
|
switch List.tl(xs) {
|
||||||
|
| exception _ => None
|
||||||
|
| a => Some(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
let init = xs => {
|
||||||
|
O.fmap(List.rev, xs |> List.rev |> tail)
|
||||||
|
}
|
||||||
|
|
||||||
|
let singleton = (x: 'a): list<'a> => list{x}
|
||||||
|
|
||||||
|
let adjust = (f, i, xs) => {
|
||||||
|
let (a, b) = splitAt(i + 1, xs)
|
||||||
|
switch a {
|
||||||
|
| _ if i < 0 => xs
|
||||||
|
| _ if i >= List.length(xs) => xs
|
||||||
|
| list{} => b
|
||||||
|
| list{a} => list{f(a), ...b}
|
||||||
|
| a =>
|
||||||
|
O.fmap(
|
||||||
|
concat'(b),
|
||||||
|
O.bind(init(a), x =>
|
||||||
|
O.fmap(F.flip(append, x), O.fmap(fmap(f), O.fmap(singleton, last(a))))
|
||||||
|
),
|
||||||
|
) |> O.default(xs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let without = (exclude, xs) => reject(x => contains(x, exclude), xs)
|
||||||
|
let update = (x, i, xs) => adjust(F.always(x), i, xs)
|
||||||
let iter = List.iter
|
let iter = List.iter
|
||||||
let findIndex = Rationale.RList.findIndex
|
|
||||||
|
let findIndex = {
|
||||||
|
let rec loop = (pred, xs, i) =>
|
||||||
|
switch xs {
|
||||||
|
| list{} => None
|
||||||
|
| list{a, ...b} => pred(a) ? Some(i) : loop(pred, b, i + 1)
|
||||||
|
}
|
||||||
|
(pred, xs) => loop(pred, xs, 0)
|
||||||
|
}
|
||||||
|
|
||||||
let headSafe = Belt.List.head
|
let headSafe = Belt.List.head
|
||||||
let tailSafe = Belt.List.tail
|
let tailSafe = Belt.List.tail
|
||||||
let headExn = Belt.List.headExn
|
let headExn = Belt.List.headExn
|
||||||
|
@ -360,7 +536,7 @@ module A = {
|
||||||
Belt.Array.getUnsafe(a, index),
|
Belt.Array.getUnsafe(a, index),
|
||||||
Belt.Array.getUnsafe(a, index + 1),
|
Belt.Array.getUnsafe(a, index + 1),
|
||||||
))
|
))
|
||||||
|> Rationale.Result.return
|
|> (x => Ok(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
let tail = Belt.Array.sliceToEnd(_, 1)
|
let tail = Belt.Array.sliceToEnd(_, 1)
|
||||||
|
@ -424,8 +600,8 @@ module A = {
|
||||||
module O = {
|
module O = {
|
||||||
let concatSomes = (optionals: array<option<'a>>): array<'a> =>
|
let concatSomes = (optionals: array<option<'a>>): array<'a> =>
|
||||||
optionals
|
optionals
|
||||||
|> Js.Array.filter(Rationale.Option.isSome)
|
|> Js.Array.filter(O.isSome)
|
||||||
|> Js.Array.map(Rationale.Option.toExn("Warning: This should not have happened"))
|
|> Js.Array.map(O.toExn("Warning: This should not have happened"))
|
||||||
let defaultEmpty = (o: option<array<'a>>): array<'a> =>
|
let defaultEmpty = (o: option<array<'a>>): array<'a> =>
|
||||||
switch o {
|
switch o {
|
||||||
| Some(o) => o
|
| Some(o) => o
|
||||||
|
@ -475,76 +651,8 @@ module A = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module Sorted = {
|
|
||||||
let min = first
|
|
||||||
let max = last
|
|
||||||
let range = (~min=min, ~max=max, a) =>
|
|
||||||
switch (min(a), max(a)) {
|
|
||||||
| (Some(min), Some(max)) => Some(max -. min)
|
|
||||||
| _ => None
|
|
||||||
}
|
|
||||||
|
|
||||||
let floatCompare: (float, float) => int = compare
|
|
||||||
|
|
||||||
let binarySearchFirstElementGreaterIndex = (ar: array<'a>, el: 'a) => {
|
|
||||||
let el = Belt.SortArray.binarySearchBy(ar, el, floatCompare)
|
|
||||||
let el = el < 0 ? el * -1 - 1 : el
|
|
||||||
switch el {
|
|
||||||
| e if e >= length(ar) => #overMax
|
|
||||||
| e if e == 0 => #underMin
|
|
||||||
| e => #firstHigher(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let concat = (t1: array<'a>, t2: array<'a>) => {
|
|
||||||
let ts = Belt.Array.concat(t1, t2)
|
|
||||||
ts |> Array.fast_sort(floatCompare)
|
|
||||||
ts
|
|
||||||
}
|
|
||||||
|
|
||||||
let concatMany = (t1: array<array<'a>>) => {
|
|
||||||
let ts = Belt.Array.concatMany(t1)
|
|
||||||
ts |> Array.fast_sort(floatCompare)
|
|
||||||
ts
|
|
||||||
}
|
|
||||||
|
|
||||||
module Floats = {
|
|
||||||
let isSorted = (ar: array<float>): bool =>
|
|
||||||
reduce(zip(ar, tail(ar)), true, (acc, (first, second)) => acc && first < second)
|
|
||||||
|
|
||||||
let makeIncrementalUp = (a, b) =>
|
|
||||||
Array.make(b - a + 1, a) |> Array.mapi((i, c) => c + i) |> Belt.Array.map(_, float_of_int)
|
|
||||||
|
|
||||||
let makeIncrementalDown = (a, b) =>
|
|
||||||
Array.make(a - b + 1, a) |> Array.mapi((i, c) => c - i) |> Belt.Array.map(_, float_of_int)
|
|
||||||
|
|
||||||
let split = (sortedArray: array<float>) => {
|
|
||||||
let continuous = []
|
|
||||||
let discrete = FloatFloatMap.empty()
|
|
||||||
Belt.Array.forEachWithIndex(sortedArray, (_, element) => {
|
|
||||||
// let maxIndex = (sortedArray |> Array.length) - 1
|
|
||||||
// let possiblySimilarElements = switch index {
|
|
||||||
// | 0 => [index + 1]
|
|
||||||
// | n if n == maxIndex => [index - 1]
|
|
||||||
// | _ => [index - 1, index + 1]
|
|
||||||
// } |> Belt.Array.map(_, r => sortedArray[r])
|
|
||||||
// let hasSimilarElement = Belt.Array.some(possiblySimilarElements, r => r == element)
|
|
||||||
let hasSimilarElement = false
|
|
||||||
hasSimilarElement
|
|
||||||
? FloatFloatMap.increment(element, discrete)
|
|
||||||
: {
|
|
||||||
let _ = Js.Array.push(element, continuous)
|
|
||||||
}
|
|
||||||
|
|
||||||
()
|
|
||||||
})
|
|
||||||
|
|
||||||
(continuous, discrete)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module Floats = {
|
module Floats = {
|
||||||
|
type t = array<float>
|
||||||
let mean = Jstat.mean
|
let mean = Jstat.mean
|
||||||
let geomean = Jstat.geomean
|
let geomean = Jstat.geomean
|
||||||
let mode = Jstat.mode
|
let mode = Jstat.mode
|
||||||
|
@ -553,14 +661,31 @@ module A = {
|
||||||
let sum = Jstat.sum
|
let sum = Jstat.sum
|
||||||
let random = Js.Math.random_int
|
let random = Js.Math.random_int
|
||||||
|
|
||||||
|
let floatCompare: (float, float) => int = compare
|
||||||
|
let sort = t => {
|
||||||
|
let r = t
|
||||||
|
r |> Array.fast_sort(floatCompare)
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
let getNonFinite = (t: t) => Belt.Array.getBy(t, r => !Js.Float.isFinite(r))
|
||||||
|
let getBelowZero = (t: t) => Belt.Array.getBy(t, r => r < 0.0)
|
||||||
|
|
||||||
|
let isSorted = (t: t): bool =>
|
||||||
|
if Array.length(t) < 1 {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
reduce(zip(t, tail(t)), true, (acc, (first, second)) => acc && first < second)
|
||||||
|
}
|
||||||
|
|
||||||
//Passing true for the exclusive parameter excludes both endpoints of the range.
|
//Passing true for the exclusive parameter excludes both endpoints of the range.
|
||||||
//https://jstat.github.io/all.html
|
//https://jstat.github.io/all.html
|
||||||
let percentile = (a, b) => Jstat.percentile(a, b, false)
|
let percentile = (a, b) => Jstat.percentile(a, b, false)
|
||||||
|
|
||||||
// Gives an array with all the differences between values
|
// Gives an array with all the differences between values
|
||||||
// diff([1,5,3,7]) = [4,-2,4]
|
// diff([1,5,3,7]) = [4,-2,4]
|
||||||
let diff = (arr: array<float>): array<float> =>
|
let diff = (t: t): array<float> =>
|
||||||
Belt.Array.zipBy(arr, Belt.Array.sliceToEnd(arr, 1), (left, right) => right -. left)
|
Belt.Array.zipBy(t, Belt.Array.sliceToEnd(t, 1), (left, right) => right -. left)
|
||||||
|
|
||||||
exception RangeError(string)
|
exception RangeError(string)
|
||||||
let range = (min: float, max: float, n: int): array<float> =>
|
let range = (min: float, max: float, n: int): array<float> =>
|
||||||
|
@ -578,18 +703,104 @@ module A = {
|
||||||
|
|
||||||
let min = Js.Math.minMany_float
|
let min = Js.Math.minMany_float
|
||||||
let max = Js.Math.maxMany_float
|
let max = Js.Math.maxMany_float
|
||||||
|
|
||||||
|
module Sorted = {
|
||||||
|
let min = first
|
||||||
|
let max = last
|
||||||
|
let range = (~min=min, ~max=max, a) =>
|
||||||
|
switch (min(a), max(a)) {
|
||||||
|
| (Some(min), Some(max)) => Some(max -. min)
|
||||||
|
| _ => None
|
||||||
|
}
|
||||||
|
|
||||||
|
let binarySearchFirstElementGreaterIndex = (ar: array<'a>, el: 'a) => {
|
||||||
|
let el = Belt.SortArray.binarySearchBy(ar, el, floatCompare)
|
||||||
|
let el = el < 0 ? el * -1 - 1 : el
|
||||||
|
switch el {
|
||||||
|
| e if e >= length(ar) => #overMax
|
||||||
|
| e if e == 0 => #underMin
|
||||||
|
| e => #firstHigher(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let concat = (t1: array<'a>, t2: array<'a>) => Belt.Array.concat(t1, t2)->sort
|
||||||
|
|
||||||
|
let concatMany = (t1: array<array<'a>>) => Belt.Array.concatMany(t1)->sort
|
||||||
|
|
||||||
|
let makeIncrementalUp = (a, b) =>
|
||||||
|
Array.make(b - a + 1, a) |> Array.mapi((i, c) => c + i) |> Belt.Array.map(_, float_of_int)
|
||||||
|
|
||||||
|
let makeIncrementalDown = (a, b) =>
|
||||||
|
Array.make(a - b + 1, a) |> Array.mapi((i, c) => c - i) |> Belt.Array.map(_, float_of_int)
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function goes through a sorted array and divides it into two different clusters:
|
||||||
|
continuous samples and discrete samples. The discrete samples are stored in a mutable map.
|
||||||
|
Samples are thought to be discrete if they have any duplicates.
|
||||||
|
*/
|
||||||
|
let _splitContinuousAndDiscreteForDuplicates = (sortedArray: array<float>) => {
|
||||||
|
let continuous: array<float> = []
|
||||||
|
let discrete = FloatFloatMap.empty()
|
||||||
|
Belt.Array.forEachWithIndex(sortedArray, (index, element) => {
|
||||||
|
let maxIndex = (sortedArray |> Array.length) - 1
|
||||||
|
let possiblySimilarElements = switch index {
|
||||||
|
| 0 => [index + 1]
|
||||||
|
| n if n == maxIndex => [index - 1]
|
||||||
|
| _ => [index - 1, index + 1]
|
||||||
|
} |> Belt.Array.map(_, r => sortedArray[r])
|
||||||
|
let hasSimilarElement = Belt.Array.some(possiblySimilarElements, r => r == element)
|
||||||
|
hasSimilarElement
|
||||||
|
? FloatFloatMap.increment(element, discrete)
|
||||||
|
: {
|
||||||
|
let _ = Js.Array.push(element, continuous)
|
||||||
|
}
|
||||||
|
|
||||||
|
()
|
||||||
|
})
|
||||||
|
|
||||||
|
(continuous, discrete)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function works very similarly to splitContinuousAndDiscreteForDuplicates. The one major difference
|
||||||
|
is that you can specify a minDiscreteWeight. If the min discreet weight is 4, that would mean that
|
||||||
|
at least four elements needed from a specific value for that to be kept as discrete. This is important
|
||||||
|
because in some cases, we can expect that some common elements will be generated by regular operations.
|
||||||
|
The final continous array will be sorted.
|
||||||
|
*/
|
||||||
|
let splitContinuousAndDiscreteForMinWeight = (
|
||||||
|
sortedArray: array<float>,
|
||||||
|
~minDiscreteWeight: int,
|
||||||
|
) => {
|
||||||
|
let (continuous, discrete) = _splitContinuousAndDiscreteForDuplicates(sortedArray)
|
||||||
|
let keepFn = v => Belt.Float.toInt(v) >= minDiscreteWeight
|
||||||
|
let (discreteToKeep, discreteToIntegrate) = FloatFloatMap.partition(
|
||||||
|
((_, v)) => keepFn(v),
|
||||||
|
discrete,
|
||||||
|
)
|
||||||
|
let newContinousSamples =
|
||||||
|
discreteToIntegrate->FloatFloatMap.toArray
|
||||||
|
|> fmap(((k, v)) => Belt.Array.makeBy(Belt.Float.toInt(v), _ => k))
|
||||||
|
|> Belt.Array.concatMany
|
||||||
|
let newContinuous = concat(continuous, newContinousSamples)
|
||||||
|
newContinuous |> Array.fast_sort(floatCompare)
|
||||||
|
(newContinuous, discreteToKeep)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
module Sorted = Floats.Sorted
|
||||||
}
|
}
|
||||||
|
|
||||||
module A2 = {
|
module A2 = {
|
||||||
let fmap = (a, b) => A.fmap(b, a)
|
let fmap = (a, b) => A.fmap(b, a)
|
||||||
let joinWith = (a, b) => A.joinWith(b, a)
|
let joinWith = (a, b) => A.joinWith(b, a)
|
||||||
|
let filter = (a, b) => A.filter(b, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
module JsArray = {
|
module JsArray = {
|
||||||
let concatSomes = (optionals: Js.Array.t<option<'a>>): Js.Array.t<'a> =>
|
let concatSomes = (optionals: Js.Array.t<option<'a>>): Js.Array.t<'a> =>
|
||||||
optionals
|
optionals
|
||||||
|> Js.Array.filter(Rationale.Option.isSome)
|
|> Js.Array.filter(O.isSome)
|
||||||
|> Js.Array.map(Rationale.Option.toExn("Warning: This should not have happened"))
|
|> Js.Array.map(O.toExn("Warning: This should not have happened"))
|
||||||
let filter = Js.Array.filter
|
let filter = Js.Array.filter
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,18 @@ type distToFloatOperation = [
|
||||||
|
|
||||||
module Convolution = {
|
module Convolution = {
|
||||||
type t = convolutionOperation
|
type t = convolutionOperation
|
||||||
|
//Only a selection of operations are supported by convolution.
|
||||||
|
let fromAlgebraicOperation = (op: algebraicOperation): option<convolutionOperation> =>
|
||||||
|
switch op {
|
||||||
|
| #Add => Some(#Add)
|
||||||
|
| #Subtract => Some(#Subtract)
|
||||||
|
| #Multiply => Some(#Multiply)
|
||||||
|
| #Divide | #Power | #Logarithm => None
|
||||||
|
}
|
||||||
|
|
||||||
|
let canDoAlgebraicOperation = (op: algebraicOperation): bool =>
|
||||||
|
fromAlgebraicOperation(op)->E.O.isSome
|
||||||
|
|
||||||
let toFn: (t, float, float) => float = x =>
|
let toFn: (t, float, float) => float = x =>
|
||||||
switch x {
|
switch x {
|
||||||
| #Add => \"+."
|
| #Add => \"+."
|
||||||
|
|
|
@ -4,6 +4,42 @@ type xyShape = {
|
||||||
ys: array<float>,
|
ys: array<float>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type propertyName = string
|
||||||
|
|
||||||
|
@genType
|
||||||
|
type rec error =
|
||||||
|
| NotSorted(propertyName)
|
||||||
|
| IsEmpty(propertyName)
|
||||||
|
| NotFinite(propertyName, float)
|
||||||
|
| DifferentLengths({p1Name: string, p2Name: string, p1Length: int, p2Length: int})
|
||||||
|
| MultipleErrors(array<error>)
|
||||||
|
|
||||||
|
@genType
|
||||||
|
module Error = {
|
||||||
|
let mapErrorArrayToError = (errors: array<error>): option<error> => {
|
||||||
|
switch errors {
|
||||||
|
| [] => None
|
||||||
|
| [error] => Some(error)
|
||||||
|
| _ => Some(MultipleErrors(errors))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let rec toString = (t: error) =>
|
||||||
|
switch t {
|
||||||
|
| NotSorted(propertyName) => `${propertyName} is not sorted`
|
||||||
|
| IsEmpty(propertyName) => `${propertyName} is empty`
|
||||||
|
| NotFinite(propertyName, exampleValue) =>
|
||||||
|
`${propertyName} is not finite. Example value: ${E.Float.toString(exampleValue)}`
|
||||||
|
| DifferentLengths({p1Name, p2Name, p1Length, p2Length}) =>
|
||||||
|
`${p1Name} and ${p2Name} have different lengths. ${p1Name} has length ${E.I.toString(
|
||||||
|
p1Length,
|
||||||
|
)} and ${p2Name} has length ${E.I.toString(p2Length)}`
|
||||||
|
| MultipleErrors(errors) =>
|
||||||
|
`Multiple Errors: ${E.A2.fmap(errors, toString)->E.A2.fmap(r => `[${r}]`)
|
||||||
|
|> E.A.joinWith(", ")}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@genType
|
@genType
|
||||||
type interpolationStrategy = [
|
type interpolationStrategy = [
|
||||||
| #Stepwise
|
| #Stepwise
|
||||||
|
@ -60,6 +96,44 @@ module T = {
|
||||||
let fromZippedArray = (pairs: array<(float, float)>): t => pairs |> Belt.Array.unzip |> fromArray
|
let fromZippedArray = (pairs: array<(float, float)>): t => pairs |> Belt.Array.unzip |> fromArray
|
||||||
let equallyDividedXs = (t: t, newLength) => E.A.Floats.range(minX(t), maxX(t), newLength)
|
let equallyDividedXs = (t: t, newLength) => E.A.Floats.range(minX(t), maxX(t), newLength)
|
||||||
let toJs = (t: t) => {"xs": t.xs, "ys": t.ys}
|
let toJs = (t: t) => {"xs": t.xs, "ys": t.ys}
|
||||||
|
|
||||||
|
module Validator = {
|
||||||
|
let fnName = "XYShape validate"
|
||||||
|
let notSortedError = (p: string): error => NotSorted(p)
|
||||||
|
let notFiniteError = (p, exampleValue): error => NotFinite(p, exampleValue)
|
||||||
|
let isEmptyError = (propertyName): error => IsEmpty(propertyName)
|
||||||
|
let differentLengthsError = (t): error => DifferentLengths({
|
||||||
|
p1Name: "Xs",
|
||||||
|
p2Name: "Ys",
|
||||||
|
p1Length: E.A.length(xs(t)),
|
||||||
|
p2Length: E.A.length(ys(t)),
|
||||||
|
})
|
||||||
|
|
||||||
|
let areXsSorted = (t: t) => E.A.Floats.isSorted(xs(t))
|
||||||
|
let areXsEmpty = (t: t) => E.A.length(xs(t)) == 0
|
||||||
|
let getNonFiniteXs = (t: t) => t->xs->E.A.Floats.getNonFinite
|
||||||
|
let getNonFiniteYs = (t: t) => t->ys->E.A.Floats.getNonFinite
|
||||||
|
|
||||||
|
let validate = (t: t) => {
|
||||||
|
let xsNotSorted = areXsSorted(t) ? None : Some(notSortedError("Xs"))
|
||||||
|
let xsEmpty = areXsEmpty(t) ? Some(isEmptyError("Xs")) : None
|
||||||
|
let differentLengths =
|
||||||
|
E.A.length(xs(t)) !== E.A.length(ys(t)) ? Some(differentLengthsError(t)) : None
|
||||||
|
let xsNotFinite = getNonFiniteXs(t)->E.O2.fmap(notFiniteError("Xs"))
|
||||||
|
let ysNotFinite = getNonFiniteYs(t)->E.O2.fmap(notFiniteError("Ys"))
|
||||||
|
[xsNotSorted, xsEmpty, differentLengths, xsNotFinite, ysNotFinite]
|
||||||
|
->E.A.O.concatSomes
|
||||||
|
->Error.mapErrorArrayToError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let make = (~xs: array<float>, ~ys: array<float>) => {
|
||||||
|
let attempt: t = {xs: xs, ys: ys}
|
||||||
|
switch Validator.validate(attempt) {
|
||||||
|
| Some(error) => Error(error)
|
||||||
|
| None => Ok(attempt)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module Ts = {
|
module Ts = {
|
||||||
|
|
7
packages/website/docs/Discussions/Gallery.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
sidebar_position: 6
|
||||||
|
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
|
|
@ -1,12 +1,10 @@
|
||||||
---
|
---
|
||||||
sidebar_position: 5
|
sidebar_position: 5
|
||||||
|
title: Three Formats of Distributions
|
||||||
|
author: Ozzie Gooen
|
||||||
|
date: 02-19-2022
|
||||||
---
|
---
|
||||||
|
|
||||||
# Three Formats of Distributions
|
|
||||||
|
|
||||||
_Author: Ozzie Gooen_
|
|
||||||
_Written on: Feb 19, 2022_
|
|
||||||
|
|
||||||
Probability distributions have several subtle possible formats. Three important ones that we deal with in Squiggle are symbolic, sample set, and graph formats.
|
Probability distributions have several subtle possible formats. Three important ones that we deal with in Squiggle are symbolic, sample set, and graph formats.
|
||||||
|
|
||||||
_Symbolic_ formats are just the math equations. `normal(5,3)` is the symbolic representation of a normal distribution.
|
_Symbolic_ formats are just the math equations. `normal(5,3)` is the symbolic representation of a normal distribution.
|
|
@ -1,39 +1,53 @@
|
||||||
---
|
---
|
||||||
sidebar_position: 2
|
sidebar_position: 2
|
||||||
|
title: Language Basics
|
||||||
---
|
---
|
||||||
|
|
||||||
import { SquiggleEditor } from "../../src/components/SquiggleEditor";
|
import { SquiggleEditor } from "../../src/components/SquiggleEditor";
|
||||||
|
|
||||||
# Squiggle Language
|
## Expressions
|
||||||
|
|
||||||
The squiggle language has a very simple syntax. The best way to get to understand
|
A distribution
|
||||||
it is by simply looking at examples.
|
|
||||||
|
|
||||||
## Basic Language
|
<SquiggleEditor initialSquiggleString={`mixture(1 to 2, 3, [0.3, 0.7])`} />
|
||||||
|
|
||||||
As an example:
|
A number
|
||||||
|
|
||||||
|
<SquiggleEditor initialSquiggleString="4.321e-3" />
|
||||||
|
|
||||||
|
Arrays
|
||||||
|
|
||||||
|
<SquiggleEditor
|
||||||
|
initialSquiggleString={`[beta(1,10), 4, isNormalized(toSampleSet(1 to 2))]`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
Records
|
||||||
|
|
||||||
|
<SquiggleEditor
|
||||||
|
initialSquiggleString={`d = {dist: triangular(0, 1, 2), weight: 0.25}
|
||||||
|
d.dist`}
|
||||||
|
/>
|
||||||
|
|
||||||
|
## Statements
|
||||||
|
|
||||||
|
A statement assigns expressions to names. It looks like `<symbol> = <expression>`
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`value_of_work = 10 to 70
|
initialSquiggleString={`value_of_work = 10 to 70
|
||||||
value_of_work`}
|
5 + value_of_work / 75`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
Squiggle can declare variables (`value_of_work = 10 to 70`) and declare exports
|
### Functions
|
||||||
(the lone `value_of_work` line). Variables can be used later in a squiggle program
|
|
||||||
and even in other notebooks!
|
|
||||||
|
|
||||||
An export is rendered to the output view so you can see your result.
|
We can define functions
|
||||||
|
|
||||||
the exports can be expressions, such as:
|
|
||||||
|
|
||||||
<SquiggleEditor initialSquiggleString="normal(0,1)" />
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
Squiggle supports functions, including the rendering of functions:
|
|
||||||
|
|
||||||
<SquiggleEditor
|
<SquiggleEditor
|
||||||
initialSquiggleString={`ozzie_estimate(t) = lognormal({mean: 3 + (t+.1)^2.5, stdev: 8})
|
initialSquiggleString={`ozzie_estimate(t) = lognormal(1, t ^ 1.01)
|
||||||
ozzie_estimate
|
nuño_estimate(t, m) = mixture(0.5 to 2, normal(m, t ^ 1.25))
|
||||||
`}
|
ozzie_estimate(5) * nuño_estimate(5.01, 1)`}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
## See more
|
||||||
|
|
||||||
|
- [Functions reference](https://squiggle-language.com/docs/Features/Functions)
|
||||||
|
- [Gallery](https://squiggle-language.com/docs/Discussions/Gallery)
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
---
|
---
|
||||||
sidebar_position: 3
|
sidebar_position: 3
|
||||||
|
title: Node Packages
|
||||||
---
|
---
|
||||||
|
|
||||||
# Javascript Libraries
|
|
||||||
|
|
||||||
There are two JavaScript packages currently available for Squiggle:
|
There are two JavaScript packages currently available for Squiggle:
|
||||||
|
|
||||||
- [`@quri/squiggle-lang`](https://www.npmjs.com/package/@quri/squiggle-lang)
|
- [`@quri/squiggle-lang`](https://www.npmjs.com/package/@quri/squiggle-lang) ![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-lang.svg)
|
||||||
- [`@quri/squiggle-components`](https://www.npmjs.com/package/@quri/squiggle-components)
|
- [`@quri/squiggle-components`](https://www.npmjs.com/package/@quri/squiggle-components) ![npm version](https://badge.fury.io/js/@quri%2Fsquiggle-components.svg)
|
||||||
|
|
||||||
Types are available for both packages.
|
Types are available for both packages.
|
||||||
|
|
||||||
|
@ -23,8 +22,8 @@ argument allows you to pass an environment previously created by another `run`
|
||||||
call. Passing this environment will mean that all previously declared variables
|
call. Passing this environment will mean that all previously declared variables
|
||||||
in the previous environment will be made available.
|
in the previous environment will be made available.
|
||||||
|
|
||||||
The return type of `run` is a bit complicated, and comes from auto generated js
|
The return type of `run` is a bit complicated, and comes from auto generated `js`
|
||||||
code that comes from rescript. I highly recommend using typescript when using
|
code that comes from rescript. We highly recommend using typescript when using
|
||||||
this library to help navigate the return type.
|
this library to help navigate the return type.
|
||||||
|
|
||||||
## Squiggle Components
|
## Squiggle Components
|
|
@ -1,6 +1,9 @@
|
||||||
# Processing confidence intervals
|
---
|
||||||
|
title: Processing Confidence Intervals
|
||||||
|
author: Nuño Sempere
|
||||||
|
---
|
||||||
|
|
||||||
This page explains what we are doing when we take a 95% confidence interval, and we get a mean and a standard deviation from it
|
This page explains what we are doing when we take a 90% confidence interval, and we get a mean and a standard deviation from it.
|
||||||
|
|
||||||
## For normals
|
## For normals
|
||||||
|
|
||||||
|
@ -19,10 +22,7 @@ module Normal = {
|
||||||
We know that for a normal with mean $\mu$ and standard deviation $\sigma$,
|
We know that for a normal with mean $\mu$ and standard deviation $\sigma$,
|
||||||
|
|
||||||
$$
|
$$
|
||||||
|
a \cdot Normal(\mu, \sigma) = Normal(a \cdot \mu, |a| \cdot \sigma)
|
||||||
a \cdot Normal(\mu, \sigma) = Normal(a\cdot \mu, |a|\cdot \sigma)
|
|
||||||
|
|
||||||
|
|
||||||
$$
|
$$
|
||||||
|
|
||||||
We can now look at the inverse cdf of a $Normal(0,1)$. We find that the 95% point is reached at $1.6448536269514722$. ([source](https://stackoverflow.com/questions/20626994/how-to-calculate-the-inverse-of-the-normal-cumulative-distribution-function-in-p)) This means that the 90% confidence interval is $[-1.6448536269514722, 1.6448536269514722]$, which has a width of $2 \cdot 1.6448536269514722$.
|
We can now look at the inverse cdf of a $Normal(0,1)$. We find that the 95% point is reached at $1.6448536269514722$. ([source](https://stackoverflow.com/questions/20626994/how-to-calculate-the-inverse-of-the-normal-cumulative-distribution-function-in-p)) This means that the 90% confidence interval is $[-1.6448536269514722, 1.6448536269514722]$, which has a width of $2 \cdot 1.6448536269514722$.
|
||||||
|
@ -30,3 +30,5 @@ We can now look at the inverse cdf of a $Normal(0,1)$. We find that the 95% poin
|
||||||
So then, if we take a $Normal(0,1)$ and we multiply it by $\frac{(high -. low)}{(2. *. 1.6448536269514722)}$, it's 90% confidence interval will be multiplied by the same amount. Then we just have to shift it by the mean to get our target normal.
|
So then, if we take a $Normal(0,1)$ and we multiply it by $\frac{(high -. low)}{(2. *. 1.6448536269514722)}$, it's 90% confidence interval will be multiplied by the same amount. Then we just have to shift it by the mean to get our target normal.
|
||||||
|
|
||||||
## For lognormals
|
## For lognormals
|
||||||
|
|
||||||
|
TODO
|
|
@ -1,10 +1,16 @@
|
||||||
---
|
---
|
||||||
sidebar_position: 1
|
sidebar_position: 1
|
||||||
|
title: Introduction
|
||||||
---
|
---
|
||||||
|
|
||||||
# Squiggle
|
Squiggle is an _estimation language_, and a syntax for _calculating and expressing beliefs_ involving uncertainty. It has use cases in forecasting and writing evaluations.
|
||||||
|
|
||||||
Squiggle is a language for writing calculations under uncertainty. It has use
|
## Get started
|
||||||
cases in forecasting and writing better evaluations.
|
|
||||||
|
|
||||||
The best way to get started with Squiggle is to [try it out yourself](https://playground.squiggle-language.com/).
|
- [Gallery](https://www.squiggle-language.com/docs/Discussions/Gallery)
|
||||||
|
- [Squiggle playground](https://squiggle-language.com/playground)
|
||||||
|
- [Language basics](https://www.squiggle-language.com/docs/Features/Language)
|
||||||
|
- [Squiggle functions source of truth](https://www.squiggle-language.com/docs/Features/Functions)
|
||||||
|
- [Known bugs](https://www.squiggle-language.com/docs/Discussions/Bugs)
|
||||||
|
- [Original lesswrong sequence](https://www.lesswrong.com/s/rDe8QE5NvXcZYzgZ3)
|
||||||
|
- [Author your squiggle models as Observable notebooks](https://observablehq.com/@hazelfire/squiggle)
|
||||||
|
|
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 12 KiB |
|
@ -1,170 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1088" height="687.962" viewBox="0 0 1088 687.962">
|
|
||||||
<g id="Group_12" data-name="Group 12" transform="translate(-57 -56)">
|
|
||||||
<g id="Group_11" data-name="Group 11" transform="translate(57 56)">
|
|
||||||
<path id="Path_83" data-name="Path 83" d="M1017.81,560.461c-5.27,45.15-16.22,81.4-31.25,110.31-20,38.52-54.21,54.04-84.77,70.28a193.275,193.275,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.282,657.282,0,0,0-104.09-13.16q-14.97-.675-29.97-.67c-15.42.02-293.07,5.29-360.67-131.57-16.69-33.76-28.13-75-32.24-125.27-11.63-142.12,52.29-235.46,134.74-296.47,155.97-115.41,369.76-110.57,523.43,7.88C941.15,276.621,1036.99,396.031,1017.81,560.461Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_84" data-name="Path 84" d="M986.56,670.771c-20,38.52-47.21,64.04-77.77,80.28a193.272,193.272,0,0,1-27.46,11.94c-55.61,19.3-117.85,14.18-166.74,3.99a657.3,657.3,0,0,0-104.09-13.16q-14.97-.675-29.97-.67-23.13.03-46.25,1.72c-100.17,7.36-253.82-6.43-321.42-143.29L382,283.981,444.95,445.6l20.09,51.59,55.37-75.98L549,381.981l130.2,149.27,36.8-81.27L970.78,657.9l14.21,11.59Z" transform="translate(-56 -106.019)" fill="#f2f2f2"/>
|
|
||||||
<path id="Path_85" data-name="Path 85" d="M302,282.962l26-57,36,83-31-60Z" opacity="0.1"/>
|
|
||||||
<path id="Path_86" data-name="Path 86" d="M610.5,753.821q-14.97-.675-29.97-.67L465.04,497.191Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
|
||||||
<path id="Path_87" data-name="Path 87" d="M464.411,315.191,493,292.962l130,150-132-128Z" opacity="0.1"/>
|
|
||||||
<path id="Path_88" data-name="Path 88" d="M908.79,751.051a193.265,193.265,0,0,1-27.46,11.94L679.2,531.251Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
|
||||||
<circle id="Ellipse_11" data-name="Ellipse 11" cx="3" cy="3" r="3" transform="translate(479 98.962)" fill="#f2f2f2"/>
|
|
||||||
<circle id="Ellipse_12" data-name="Ellipse 12" cx="3" cy="3" r="3" transform="translate(396 201.962)" fill="#f2f2f2"/>
|
|
||||||
<circle id="Ellipse_13" data-name="Ellipse 13" cx="2" cy="2" r="2" transform="translate(600 220.962)" fill="#f2f2f2"/>
|
|
||||||
<circle id="Ellipse_14" data-name="Ellipse 14" cx="2" cy="2" r="2" transform="translate(180 265.962)" fill="#f2f2f2"/>
|
|
||||||
<circle id="Ellipse_15" data-name="Ellipse 15" cx="2" cy="2" r="2" transform="translate(612 96.962)" fill="#f2f2f2"/>
|
|
||||||
<circle id="Ellipse_16" data-name="Ellipse 16" cx="2" cy="2" r="2" transform="translate(736 192.962)" fill="#f2f2f2"/>
|
|
||||||
<circle id="Ellipse_17" data-name="Ellipse 17" cx="2" cy="2" r="2" transform="translate(858 344.962)" fill="#f2f2f2"/>
|
|
||||||
<path id="Path_89" data-name="Path 89" d="M306,121.222h-2.76v-2.76h-1.48v2.76H299V122.7h2.76v2.759h1.48V122.7H306Z" fill="#f2f2f2"/>
|
|
||||||
<path id="Path_90" data-name="Path 90" d="M848,424.222h-2.76v-2.76h-1.48v2.76H841V425.7h2.76v2.759h1.48V425.7H848Z" fill="#f2f2f2"/>
|
|
||||||
<path id="Path_91" data-name="Path 91" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_92" data-name="Path 92" d="M1144,719.981c0,16.569-243.557,74-544,74s-544-57.431-544-74,243.557,14,544,14S1144,703.413,1144,719.981Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
|
||||||
<ellipse id="Ellipse_18" data-name="Ellipse 18" cx="544" cy="30" rx="544" ry="30" transform="translate(0 583.962)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_93" data-name="Path 93" d="M624,677.981c0,33.137-14.775,24-33,24s-33,9.137-33-24,33-96,33-96S624,644.844,624,677.981Z" transform="translate(-56 -106.019)" fill="#ff6584"/>
|
|
||||||
<path id="Path_94" data-name="Path 94" d="M606,690.66c0,15.062-6.716,10.909-15,10.909s-15,4.153-15-10.909,15-43.636,15-43.636S606,675.6,606,690.66Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
|
||||||
<rect id="Rectangle_97" data-name="Rectangle 97" width="92" height="18" rx="9" transform="translate(489 604.962)" fill="#2f2e41"/>
|
|
||||||
<rect id="Rectangle_98" data-name="Rectangle 98" width="92" height="18" rx="9" transform="translate(489 586.962)" fill="#2f2e41"/>
|
|
||||||
<path id="Path_95" data-name="Path 95" d="M193,596.547c0,55.343,34.719,100.126,77.626,100.126" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_96" data-name="Path 96" d="M270.626,696.673c0-55.965,38.745-101.251,86.626-101.251" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
|
||||||
<path id="Path_97" data-name="Path 97" d="M221.125,601.564c0,52.57,22.14,95.109,49.5,95.109" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
|
||||||
<path id="Path_98" data-name="Path 98" d="M270.626,696.673c0-71.511,44.783-129.377,100.126-129.377" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_99" data-name="Path 99" d="M254.3,697.379s11.009-.339,14.326-2.7,16.934-5.183,17.757-1.395,16.544,18.844,4.115,18.945-28.879-1.936-32.19-3.953S254.3,697.379,254.3,697.379Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
|
||||||
<path id="Path_100" data-name="Path 100" d="M290.716,710.909c-12.429.1-28.879-1.936-32.19-3.953-2.522-1.536-3.527-7.048-3.863-9.591l-.368.014s.7,8.879,4.009,10.9,19.761,4.053,32.19,3.953c3.588-.029,4.827-1.305,4.759-3.2C294.755,710.174,293.386,710.887,290.716,710.909Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
|
||||||
<path id="Path_101" data-name="Path 101" d="M777.429,633.081c0,38.029,23.857,68.8,53.341,68.8" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_102" data-name="Path 102" d="M830.769,701.882c0-38.456,26.623-69.575,59.525-69.575" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
|
||||||
<path id="Path_103" data-name="Path 103" d="M796.755,636.528c0,36.124,15.213,65.354,34.014,65.354" transform="translate(-56 -106.019)" fill="#6c63ff"/>
|
|
||||||
<path id="Path_104" data-name="Path 104" d="M830.769,701.882c0-49.139,30.773-88.9,68.8-88.9" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_105" data-name="Path 105" d="M819.548,702.367s7.565-.233,9.844-1.856,11.636-3.562,12.2-.958,11.368,12.949,2.828,13.018-19.844-1.33-22.119-2.716S819.548,702.367,819.548,702.367Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
|
||||||
<path id="Path_106" data-name="Path 106" d="M844.574,711.664c-8.54.069-19.844-1.33-22.119-2.716-1.733-1.056-2.423-4.843-2.654-6.59l-.253.01s.479,6.1,2.755,7.487,13.579,2.785,22.119,2.716c2.465-.02,3.317-.9,3.27-2.2C847.349,711.159,846.409,711.649,844.574,711.664Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
|
||||||
<path id="Path_107" data-name="Path 107" d="M949.813,724.718s11.36-1.729,14.5-4.591,16.89-7.488,18.217-3.667,19.494,17.447,6.633,19.107-30.153,1.609-33.835-.065S949.813,724.718,949.813,724.718Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
|
||||||
<path id="Path_108" data-name="Path 108" d="M989.228,734.173c-12.86,1.659-30.153,1.609-33.835-.065-2.8-1.275-4.535-6.858-5.2-9.45l-.379.061s1.833,9.109,5.516,10.783,20.975,1.725,33.835.065c3.712-.479,4.836-1.956,4.529-3.906C993.319,732.907,991.991,733.817,989.228,734.173Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
|
||||||
<path id="Path_109" data-name="Path 109" d="M670.26,723.9s9.587-1.459,12.237-3.875,14.255-6.32,15.374-3.095,16.452,14.725,5.6,16.125-25.448,1.358-28.555-.055S670.26,723.9,670.26,723.9Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
|
||||||
<path id="Path_110" data-name="Path 110" d="M703.524,731.875c-10.853,1.4-25.448,1.358-28.555-.055-2.367-1.076-3.827-5.788-4.39-7.976l-.32.051s1.547,7.687,4.655,9.1,17.7,1.456,28.555.055c3.133-.4,4.081-1.651,3.822-3.3C706.977,730.807,705.856,731.575,703.524,731.875Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
|
||||||
<path id="Path_111" data-name="Path 111" d="M178.389,719.109s7.463-1.136,9.527-3.016,11.1-4.92,11.969-2.409,12.808,11.463,4.358,12.553-19.811,1.057-22.23-.043S178.389,719.109,178.389,719.109Z" transform="translate(-56 -106.019)" fill="#a8a8a8"/>
|
|
||||||
<path id="Path_112" data-name="Path 112" d="M204.285,725.321c-8.449,1.09-19.811,1.057-22.23-.043-1.842-.838-2.979-4.506-3.417-6.209l-.249.04s1.2,5.984,3.624,7.085,13.781,1.133,22.23.043c2.439-.315,3.177-1.285,2.976-2.566C206.973,724.489,206.1,725.087,204.285,725.321Z" transform="translate(-56 -106.019)" opacity="0.2"/>
|
|
||||||
<path id="Path_113" data-name="Path 113" d="M439.7,707.337c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873,42.118-36.793,93.694-36.793S439.7,677.117,439.7,707.337Z" transform="translate(-56 -106.019)" opacity="0.1"/>
|
|
||||||
<path id="Path_114" data-name="Path 114" d="M439.7,699.9c0,30.22-42.124,20.873-93.7,20.873s-93.074,9.347-93.074-20.873S295.04,663.1,346.616,663.1,439.7,669.676,439.7,699.9Z" transform="translate(-56 -106.019)" fill="#3f3d56"/>
|
|
||||||
</g>
|
|
||||||
<g id="docusaurus_keytar" transform="translate(312.271 493.733)">
|
|
||||||
<path id="Path_40" data-name="Path 40" d="M99,52h91.791V89.153H99Z" transform="translate(5.904 -14.001)" fill="#fff" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_41" data-name="Path 41" d="M24.855,163.927A21.828,21.828,0,0,1,5.947,153a21.829,21.829,0,0,0,18.908,32.782H46.71V163.927Z" transform="translate(-3 -4.634)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_42" data-name="Path 42" d="M121.861,61.1l76.514-4.782V45.39A21.854,21.854,0,0,0,176.52,23.535H78.173L75.441,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L64.513,18.8a3.154,3.154,0,0,0-5.464,0l-2.732,4.732L53.586,18.8a3.154,3.154,0,0,0-5.464,0L45.39,23.535c-.024,0-.046,0-.071,0l-4.526-4.525a3.153,3.153,0,0,0-5.276,1.414l-1.5,5.577-5.674-1.521a3.154,3.154,0,0,0-3.863,3.864L26,34.023l-5.575,1.494a3.155,3.155,0,0,0-1.416,5.278l4.526,4.526c0,.023,0,.046,0,.07L18.8,48.122a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,59.05a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,69.977a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,80.9a3.154,3.154,0,0,0,0,5.464L23.535,89.1,18.8,91.832a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,102.76a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,113.687a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,124.615a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,135.542a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,146.469a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,157.4a3.154,3.154,0,0,0,0,5.464l4.732,2.732L18.8,168.324a3.154,3.154,0,0,0,0,5.464l4.732,2.732A21.854,21.854,0,0,0,45.39,198.375H176.52a21.854,21.854,0,0,0,21.855-21.855V89.1l-76.514-4.782a11.632,11.632,0,0,1,0-23.219" transform="translate(-1.681 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_43" data-name="Path 43" d="M143,186.71h32.782V143H143Z" transform="translate(9.984 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_44" data-name="Path 44" d="M196.71,159.855a5.438,5.438,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(10.912 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_45" data-name="Path 45" d="M153,124.855h32.782V103H153Z" transform="translate(10.912 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_46" data-name="Path 46" d="M194.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.814,2.814,0,0,0,.349.035" transform="translate(12.767 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_47" data-name="Path 47" d="M65.087,56.891a2.732,2.732,0,0,1-2.732-2.732,8.2,8.2,0,0,0-16.391,0,2.732,2.732,0,0,1-5.464,0,13.659,13.659,0,0,1,27.319,0,2.732,2.732,0,0,1-2.732,2.732" transform="translate(0.478 -15.068)" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_48" data-name="Path 48" d="M103,191.347h65.565a21.854,21.854,0,0,0,21.855-21.855V93H124.855A21.854,21.854,0,0,0,103,114.855Z" transform="translate(6.275 -10.199)" fill="#ffff50" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_49" data-name="Path 49" d="M173.216,129.787H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0-54.434H118.535a1.093,1.093,0,1,1,0-2.185h54.681a1.093,1.093,0,0,1,0,2.185m0,21.652H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186m0,21.855H118.535a1.093,1.093,0,1,1,0-2.186h54.681a1.093,1.093,0,0,1,0,2.186M189.585,61.611c-.013,0-.024-.007-.037-.005-3.377.115-4.974,3.492-6.384,6.472-1.471,3.114-2.608,5.139-4.473,5.078-2.064-.074-3.244-2.406-4.494-4.874-1.436-2.835-3.075-6.049-6.516-5.929-3.329.114-4.932,3.053-6.346,5.646-1.5,2.762-2.529,4.442-4.5,4.364-2.106-.076-3.225-1.972-4.52-4.167-1.444-2.443-3.112-5.191-6.487-5.1-3.272.113-4.879,2.606-6.3,4.808-1.5,2.328-2.552,3.746-4.551,3.662-2.156-.076-3.27-1.65-4.558-3.472-1.447-2.047-3.077-4.363-6.442-4.251-3.2.109-4.807,2.153-6.224,3.954-1.346,1.709-2.4,3.062-4.621,2.977a1.093,1.093,0,0,0-.079,2.186c3.3.11,4.967-1.967,6.417-3.81,1.286-1.635,2.4-3.045,4.582-3.12,2.1-.09,3.091,1.218,4.584,3.327,1.417,2,3.026,4.277,6.263,4.394,3.391.114,5.022-2.42,6.467-4.663,1.292-2,2.406-3.734,4.535-3.807,1.959-.073,3.026,1.475,4.529,4.022,1.417,2.4,3.023,5.121,6.324,5.241,3.415.118,5.064-2.863,6.5-5.5,1.245-2.282,2.419-4.437,4.5-4.509,1.959-.046,2.981,1.743,4.492,4.732,1.412,2.79,3.013,5.95,6.365,6.071l.185,0c3.348,0,4.937-3.36,6.343-6.331,1.245-2.634,2.423-5.114,4.444-5.216Z" transform="translate(7.109 -13.11)" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_50" data-name="Path 50" d="M83,186.71h43.71V143H83Z" transform="translate(4.42 -5.561)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 109.327, 91.085)">
|
|
||||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="92.361" height="36.462" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
|
||||||
<g id="Group_2" data-name="Group 2" transform="translate(1.531 23.03)">
|
|
||||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="5.336" height="5.336" rx="1" transform="translate(16.797 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="5.336" height="5.336" rx="1" transform="translate(23.12 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="5.336" height="5.336" rx="1" transform="translate(29.444 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="5.336" height="5.336" rx="1" transform="translate(35.768 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="5.336" height="5.336" rx="1" transform="translate(42.091 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="5.336" height="5.336" rx="1" transform="translate(48.415 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="5.336" height="5.336" rx="1" transform="translate(54.739 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="5.336" height="5.336" rx="1" transform="translate(61.063 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="5.336" height="5.336" rx="1" transform="translate(67.386 0)" fill="#4a4a4a"/>
|
|
||||||
<path id="Path_51" data-name="Path 51" d="M1.093,0H14.518a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0ZM75,0H88.426a1.093,1.093,0,0,1,1.093,1.093V4.243a1.093,1.093,0,0,1-1.093,1.093H75a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,75,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group_3" data-name="Group 3" transform="translate(1.531 10.261)">
|
|
||||||
<path id="Path_52" data-name="Path 52" d="M1.093,0H6.218A1.093,1.093,0,0,1,7.31,1.093V4.242A1.093,1.093,0,0,1,6.218,5.335H1.093A1.093,1.093,0,0,1,0,4.242V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="5.336" height="5.336" rx="1" transform="translate(58.888 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="5.336" height="5.336" rx="1" transform="translate(65.212 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="5.336" height="5.336" rx="1" transform="translate(71.536 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="5.336" height="5.336" rx="1" transform="translate(77.859 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group_4" data-name="Group 4" transform="translate(91.05 9.546) rotate(180)">
|
|
||||||
<path id="Path_53" data-name="Path 53" d="M1.093,0H6.219A1.093,1.093,0,0,1,7.312,1.093v3.15A1.093,1.093,0,0,1,6.219,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.093A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="5.336" height="5.336" rx="1" transform="translate(8.299 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="5.336" height="5.336" rx="1" transform="translate(14.623 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="5.336" height="5.336" rx="1" transform="translate(20.947 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="5.336" height="5.336" rx="1" transform="translate(27.271 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="5.336" height="5.336" rx="1" transform="translate(33.594 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="5.336" height="5.336" rx="1" transform="translate(39.918 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="5.336" height="5.336" rx="1" transform="translate(46.242 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="5.336" height="5.336" rx="1" transform="translate(52.565 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="5.336" height="5.336" rx="1" transform="translate(58.889 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="5.336" height="5.336" rx="1" transform="translate(65.213 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="5.336" height="5.336" rx="1" transform="translate(71.537 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="5.336" height="5.336" rx="1" transform="translate(77.86 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group_6" data-name="Group 6" transform="translate(1.531 16.584)">
|
|
||||||
<path id="Path_54" data-name="Path 54" d="M1.093,0h7.3A1.093,1.093,0,0,1,9.485,1.093v3.15A1.093,1.093,0,0,1,8.392,5.336h-7.3A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
<g id="Group_5" data-name="Group 5" transform="translate(10.671 0)">
|
|
||||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="5.336" height="5.336" rx="1" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="5.336" height="5.336" rx="1" transform="translate(25.295 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="5.336" height="5.336" rx="1" transform="translate(31.619 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="5.336" height="5.336" rx="1" transform="translate(37.942 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="5.336" height="5.336" rx="1" transform="translate(44.265 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="5.336" height="5.336" rx="1" transform="translate(50.589 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="5.336" height="5.336" rx="1" transform="translate(56.912 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="5.336" height="5.336" rx="1" transform="translate(63.236 0)" fill="#4a4a4a"/>
|
|
||||||
</g>
|
|
||||||
<path id="Path_55" data-name="Path 55" d="M1.094,0H8A1.093,1.093,0,0,1,9.091,1.093v3.15A1.093,1.093,0,0,1,8,5.336H1.093A1.093,1.093,0,0,1,0,4.243V1.094A1.093,1.093,0,0,1,1.093,0Z" transform="translate(80.428 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group_7" data-name="Group 7" transform="translate(1.531 29.627)">
|
|
||||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="5.336" height="5.336" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="5.336" height="5.336" rx="1" transform="translate(6.324 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="5.336" height="5.336" rx="1" transform="translate(12.647 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="5.336" height="5.336" rx="1" transform="translate(18.971 0)" fill="#4a4a4a"/>
|
|
||||||
<path id="Path_56" data-name="Path 56" d="M1.093,0H31.515a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H1.093A1.093,1.093,0,0,1,0,4.244V1.093A1.093,1.093,0,0,1,1.093,0ZM34.687,0h3.942a1.093,1.093,0,0,1,1.093,1.093V4.244a1.093,1.093,0,0,1-1.093,1.093H34.687a1.093,1.093,0,0,1-1.093-1.093V1.093A1.093,1.093,0,0,1,34.687,0Z" transform="translate(25.294 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="5.336" height="5.336" rx="1" transform="translate(66.003 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="5.336" height="5.336" rx="1" transform="translate(72.327 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="5.336" height="5.336" rx="1" transform="translate(84.183 0)" fill="#4a4a4a"/>
|
|
||||||
<path id="Path_57" data-name="Path 57" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(83.59 2.273) rotate(180)" fill="#4a4a4a"/>
|
|
||||||
<path id="Path_58" data-name="Path 58" d="M5.336,0V1.18A1.093,1.093,0,0,1,4.243,2.273H1.093A1.093,1.093,0,0,1,0,1.18V0Z" transform="translate(78.255 3.063)" fill="#4a4a4a"/>
|
|
||||||
</g>
|
|
||||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="88.927" height="2.371" rx="1.085" transform="translate(1.925 1.17)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="4.986" height="1.581" rx="0.723" transform="translate(4.1 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="4.986" height="1.581" rx="0.723" transform="translate(10.923 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="4.986" height="1.581" rx="0.723" transform="translate(16.173 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="4.986" height="1.581" rx="0.723" transform="translate(21.421 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="4.986" height="1.581" rx="0.723" transform="translate(26.671 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="4.986" height="1.581" rx="0.723" transform="translate(33.232 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="4.986" height="1.581" rx="0.723" transform="translate(38.48 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="4.986" height="1.581" rx="0.723" transform="translate(43.73 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="4.986" height="1.581" rx="0.723" transform="translate(48.978 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="4.986" height="1.581" rx="0.723" transform="translate(55.54 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="4.986" height="1.581" rx="0.723" transform="translate(60.788 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="4.986" height="1.581" rx="0.723" transform="translate(66.038 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="4.986" height="1.581" rx="0.723" transform="translate(72.599 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="4.986" height="1.581" rx="0.723" transform="translate(77.847 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="4.986" height="1.581" rx="0.723" transform="translate(83.097 1.566)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
</g>
|
|
||||||
<path id="Path_59" data-name="Path 59" d="M146.71,159.855a5.439,5.439,0,0,0-.7.07c-.042-.164-.081-.329-.127-.493a5.457,5.457,0,1,0-5.4-9.372q-.181-.185-.366-.367a5.454,5.454,0,1,0-9.384-5.4c-.162-.046-.325-.084-.486-.126a5.467,5.467,0,1,0-10.788,0c-.162.042-.325.08-.486.126a5.457,5.457,0,1,0-9.384,5.4,21.843,21.843,0,1,0,36.421,21.02,5.452,5.452,0,1,0,.7-10.858" transform="translate(6.275 -6.025)" fill="#44d860" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_60" data-name="Path 60" d="M83,124.855h43.71V103H83Z" transform="translate(4.42 -9.271)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_61" data-name="Path 61" d="M134.855,116.765a2.732,2.732,0,1,0,0-5.464,2.811,2.811,0,0,0-.349.035c-.022-.082-.04-.164-.063-.246a2.733,2.733,0,0,0-1.052-5.253,2.7,2.7,0,0,0-1.648.566q-.09-.093-.184-.184a2.7,2.7,0,0,0,.553-1.633,2.732,2.732,0,0,0-5.245-1.07,10.928,10.928,0,1,0,0,21.031,2.732,2.732,0,0,0,5.245-1.07,2.7,2.7,0,0,0-.553-1.633q.093-.09.184-.184a2.7,2.7,0,0,0,1.648.566,2.732,2.732,0,0,0,1.052-5.253c.023-.081.042-.164.063-.246a2.811,2.811,0,0,0,.349.035" transform="translate(7.202 -9.377)" fill="#44d860" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_62" data-name="Path 62" d="M143.232,42.33a2.967,2.967,0,0,1-.535-.055,2.754,2.754,0,0,1-.514-.153,2.838,2.838,0,0,1-.471-.251,4.139,4.139,0,0,1-.415-.339,3.2,3.2,0,0,1-.338-.415A2.7,2.7,0,0,1,140.5,39.6a2.968,2.968,0,0,1,.055-.535,3.152,3.152,0,0,1,.152-.514,2.874,2.874,0,0,1,.252-.47,2.633,2.633,0,0,1,.753-.754,2.837,2.837,0,0,1,.471-.251,2.753,2.753,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,4.019,4.019,0,0,1,.339.415,2.786,2.786,0,0,1,.251.47,2.864,2.864,0,0,1,.208,1.049,2.77,2.77,0,0,1-.8,1.934,4.139,4.139,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459m21.855-1.366a2.789,2.789,0,0,1-1.935-.8,4.162,4.162,0,0,1-.338-.415,2.7,2.7,0,0,1-.459-1.519,2.789,2.789,0,0,1,.8-1.934,4.139,4.139,0,0,1,.415-.339,2.838,2.838,0,0,1,.471-.251,2.752,2.752,0,0,1,.514-.153,2.527,2.527,0,0,1,1.071,0,2.654,2.654,0,0,1,.983.4,4.139,4.139,0,0,1,.415.339,2.79,2.79,0,0,1,.8,1.934,3.069,3.069,0,0,1-.055.535,2.779,2.779,0,0,1-.153.514,3.885,3.885,0,0,1-.251.47,4.02,4.02,0,0,1-.339.415,4.138,4.138,0,0,1-.415.339,2.722,2.722,0,0,1-1.519.459" transform="translate(9.753 -15.532)" fill-rule="evenodd"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 31 KiB |
|
@ -1,169 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="1041.277" height="554.141" viewBox="0 0 1041.277 554.141">
|
|
||||||
<g id="Group_24" data-name="Group 24" transform="translate(-440 -263)">
|
|
||||||
<g id="Group_23" data-name="Group 23" transform="translate(439.989 262.965)">
|
|
||||||
<path id="Path_299" data-name="Path 299" d="M1040.82,611.12q-1.74,3.75-3.47,7.4-2.7,5.67-5.33,11.12c-.78,1.61-1.56,3.19-2.32,4.77-8.6,17.57-16.63,33.11-23.45,45.89A73.21,73.21,0,0,1,942.44,719l-151.65,1.65h-1.6l-13,.14-11.12.12-34.1.37h-1.38l-17.36.19h-.53l-107,1.16-95.51,1-11.11.12-69,.75H429l-44.75.48h-.48l-141.5,1.53-42.33.46a87.991,87.991,0,0,1-10.79-.54h0c-1.22-.14-2.44-.3-3.65-.49a87.38,87.38,0,0,1-51.29-27.54C116,678.37,102.75,655,93.85,629.64q-1.93-5.49-3.6-11.12C59.44,514.37,97,380,164.6,290.08q4.25-5.64,8.64-11l.07-.08c20.79-25.52,44.1-46.84,68.93-62,44-26.91,92.75-34.49,140.7-11.9,40.57,19.12,78.45,28.11,115.17,30.55,3.71.24,7.42.42,11.11.53,84.23,2.65,163.17-27.7,255.87-47.29,3.69-.78,7.39-1.55,11.12-2.28,66.13-13.16,139.49-20.1,226.73-5.51a189.089,189.089,0,0,1,26.76,6.4q5.77,1.86,11.12,4c41.64,16.94,64.35,48.24,74,87.46q1.37,5.46,2.37,11.11C1134.3,384.41,1084.19,518.23,1040.82,611.12Z" transform="translate(-79.34 -172.91)" fill="#f2f2f2"/>
|
|
||||||
<path id="Path_300" data-name="Path 300" d="M576.36,618.52a95.21,95.21,0,0,1-1.87,11.12h93.7V618.52Zm-78.25,62.81,11.11-.09V653.77c-3.81-.17-7.52-.34-11.11-.52ZM265.19,618.52v11.12h198.5V618.52ZM1114.87,279h-74V191.51q-5.35-2.17-11.12-4V279H776.21V186.58c-3.73.73-7.43,1.5-11.12,2.28V279H509.22V236.15c-3.69-.11-7.4-.29-11.11-.53V279H242.24V217c-24.83,15.16-48.14,36.48-68.93,62h-.07v.08q-4.4,5.4-8.64,11h8.64V618.52h-83q1.66,5.63,3.6,11.12h79.39v93.62a87,87,0,0,0,12.2,2.79c1.21.19,2.43.35,3.65.49h0a87.991,87.991,0,0,0,10.79.54l42.33-.46v-97H498.11v94.21l11.11-.12V629.64H765.09V721l11.12-.12V629.64H1029.7v4.77c.76-1.58,1.54-3.16,2.32-4.77q2.63-5.45,5.33-11.12,1.73-3.64,3.47-7.4v-321h76.42Q1116.23,284.43,1114.87,279ZM242.24,618.52V290.08H498.11V618.52Zm267,0V290.08H765.09V618.52Zm520.48,0H776.21V290.08H1029.7Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
|
||||||
<path id="Path_301" data-name="Path 301" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" fill="#65617d"/>
|
|
||||||
<path id="Path_302" data-name="Path 302" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l46.65-28,93.6-.78,2-.01.66-.01,2-.03,44.94-.37,2.01-.01.64-.01,2-.01L315,509.3l.38-.01,35.55-.3h.29l277.4-2.34,6.79-.05h.68l5.18-.05,37.65-.31,2-.03,1.85-.02h.96l11.71-.09,2.32-.03,3.11-.02,9.75-.09,15.47-.13,2-.02,3.48-.02h.65l74.71-.64Z" opacity="0.2"/>
|
|
||||||
<path id="Path_303" data-name="Path 303" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_304" data-name="Path 304" d="M375.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
|
||||||
<path id="Path_305" data-name="Path 305" d="M377.44,656.57v24.49a6.13,6.13,0,0,1-3.5,5.54,6,6,0,0,1-2.5.6l-34.9.74a6,6,0,0,1-2.7-.57,6.12,6.12,0,0,1-3.57-5.57V656.57Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
|
||||||
<rect id="Rectangle_137" data-name="Rectangle 137" width="47.17" height="31.5" transform="translate(680.92 483.65)" fill="#3f3d56"/>
|
|
||||||
<rect id="Rectangle_138" data-name="Rectangle 138" width="47.17" height="31.5" transform="translate(680.92 483.65)" opacity="0.1"/>
|
|
||||||
<rect id="Rectangle_139" data-name="Rectangle 139" width="47.17" height="31.5" transform="translate(678.92 483.65)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_306" data-name="Path 306" d="M298.09,483.65v4.97l-47.17,1.26v-6.23Z" opacity="0.1"/>
|
|
||||||
<path id="Path_307" data-name="Path 307" d="M460.69,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6a4,4,0,0,1,3.95,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
|
||||||
<path id="Path_308" data-name="Path 308" d="M265.19,481.32v181.2h-.05a4,4,0,0,1-3.95-3.95V485.27a4,4,0,0,1,3.95-3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
|
||||||
<path id="Path_309" data-name="Path 309" d="M194.59,319.15h177.5V467.4l-177.5,4Z" fill="#39374d"/>
|
|
||||||
<path id="Path_310" data-name="Path 310" d="M726.09,483.65v6.41l-47.17-1.26v-5.15Z" opacity="0.1"/>
|
|
||||||
<path id="Path_311" data-name="Path 311" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0L672,657.42a4,4,0,0,1-3.85-3.95V485.27a4,4,0,0,1,3.95-3.95H863.7a4,4,0,0,1,3.99,3.95Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
|
||||||
<path id="Path_312" data-name="Path 312" d="M867.69,485.27v173.3a4,4,0,0,1-4,3.95h0V481.32h0a4,4,0,0,1,4,3.95Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
|
||||||
<path id="Path_313" data-name="Path 313" d="M775.59,319.15H598.09V467.4l177.5,4Z" fill="#39374d"/>
|
|
||||||
<path id="Path_314" data-name="Path 314" d="M663.19,485.27v168.2a4,4,0,0,1-3.85,3.95l-191.65,5.1h0a4,4,0,0,1-4-3.95V485.27a4,4,0,0,1,3.95-3.95h191.6A4,4,0,0,1,663.19,485.27Z" transform="translate(-79.34 -172.91)" fill="#65617d"/>
|
|
||||||
<path id="Path_315" data-name="Path 315" d="M397.09,319.15h177.5V467.4l-177.5,4Z" fill="#4267b2"/>
|
|
||||||
<path id="Path_316" data-name="Path 316" d="M863.09,533.65v13l-151.92,1.4-1.62.03-57.74.53-1.38.02-17.55.15h-.52l-106.98.99L349.77,551.4h-.15l-44.65.42-.48.01-198.4,1.82v-15l202.51-1.33h.48l40.99-.28h.19l283.08-1.87h.29l.17-.01h.47l4.79-.03h1.46l74.49-.5,4.4-.02.98-.01Z" opacity="0.1"/>
|
|
||||||
<circle id="Ellipse_111" data-name="Ellipse 111" cx="51.33" cy="51.33" r="51.33" transform="translate(435.93 246.82)" fill="#fbbebe"/>
|
|
||||||
<path id="Path_317" data-name="Path 317" d="M617.94,550.07s-99.5,12-90,0c3.44-4.34,4.39-17.2,4.2-31.85-.06-4.45-.22-9.06-.45-13.65-1.1-22-3.75-43.5-3.75-43.5s87-41,77-8.5c-4,13.13-2.69,31.57.35,48.88.89,5.05,1.92,10,3,14.7a344.66,344.66,0,0,0,9.65,33.92Z" transform="translate(-79.34 -172.91)" fill="#fbbebe"/>
|
|
||||||
<path id="Path_318" data-name="Path 318" d="M585.47,546c11.51-2.13,23.7-6,34.53-1.54,2.85,1.17,5.47,2.88,8.39,3.86s6.12,1.22,9.16,1.91c10.68,2.42,19.34,10.55,24.9,20s8.44,20.14,11.26,30.72l6.9,25.83c6,22.45,12,45.09,13.39,68.3a2437.506,2437.506,0,0,1-250.84,1.43c5.44-10.34,11-21.31,10.54-33s-7.19-23.22-4.76-34.74c1.55-7.34,6.57-13.39,9.64-20.22,8.75-19.52,1.94-45.79,17.32-60.65,6.92-6.68,17-9.21,26.63-8.89,12.28.41,24.85,4.24,37,6.11C555.09,547.48,569.79,548.88,585.47,546Z" transform="translate(-79.34 -172.91)" fill="#ff6584"/>
|
|
||||||
<path id="Path_319" data-name="Path 319" d="M716.37,657.17l-.1,1.43v.1l-.17,2.3-1.33,18.51-1.61,22.3-.46,6.28-1,13.44v.17l-107,1-175.59,1.9v.84h-.14v-1.12l.45-14.36.86-28.06.74-23.79.07-2.37a10.53,10.53,0,0,1,11.42-10.17c4.72.4,10.85.89,18.18,1.41l3,.22c42.33,2.94,120.56,6.74,199.5,2,1.66-.09,3.33-.19,5-.31,12.24-.77,24.47-1.76,36.58-3a10.53,10.53,0,0,1,11.6,11.23Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
|
||||||
<path id="Path_320" data-name="Path 320" d="M429.08,725.44v-.84l175.62-1.91,107-1h.3v-.17l1-13.44.43-6,1.64-22.61,1.29-17.9v-.44a10.617,10.617,0,0,0-.11-2.47.3.3,0,0,0,0-.1,10.391,10.391,0,0,0-2-4.64,10.54,10.54,0,0,0-9.42-4c-12.11,1.24-24.34,2.23-36.58,3-1.67.12-3.34.22-5,.31-78.94,4.69-157.17.89-199.5-2l-3-.22c-7.33-.52-13.46-1-18.18-1.41a10.54,10.54,0,0,0-11.24,8.53,11,11,0,0,0-.18,1.64l-.68,22.16L429.54,710l-.44,14.36v1.12Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
|
||||||
<path id="Path_321" data-name="Path 321" d="M716.67,664.18l-1.23,15.33-1.83,22.85-.46,5.72-1,12.81-.06.64v.17h0l-.15,1.48.11-1.48h-.29l-107,1-175.65,1.9v-.28l.49-14.36,1-28.06.64-18.65A6.36,6.36,0,0,1,434.3,658a6.25,6.25,0,0,1,3.78-.9c2.1.17,4.68.37,7.69.59,4.89.36,10.92.78,17.94,1.22,13,.82,29.31,1.7,48,2.42,52,2,122.2,2.67,188.88-3.17,3-.26,6.1-.55,9.13-.84a6.26,6.26,0,0,1,3.48.66,5.159,5.159,0,0,1,.86.54,6.14,6.14,0,0,1,2,2.46,3.564,3.564,0,0,1,.25.61A6.279,6.279,0,0,1,716.67,664.18Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
|
||||||
<path id="Path_322" data-name="Path 322" d="M377.44,677.87v3.19a6.13,6.13,0,0,1-3.5,5.54l-40.1.77a6.12,6.12,0,0,1-3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
|
||||||
<path id="Path_323" data-name="Path 323" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
|
||||||
<path id="Path_324" data-name="Path 324" d="M298.59,515.57l-52.25,1V507.9l52.25-1Z" opacity="0.1"/>
|
|
||||||
<path id="Path_325" data-name="Path 325" d="M300.59,515.57l-52.25,1V507.9l52.25-1Z" fill="#3f3d56"/>
|
|
||||||
<path id="Path_326" data-name="Path 326" d="M758.56,679.87v3.19a6.13,6.13,0,0,0,3.5,5.54l40.1.77a6.12,6.12,0,0,0,3.57-5.57v-3Z" transform="translate(-79.34 -172.91)" opacity="0.1"/>
|
|
||||||
<path id="Path_327" data-name="Path 327" d="M678.72,517.57l52.25,1V509.9l-52.25-1Z" opacity="0.1"/>
|
|
||||||
<path id="Path_328" data-name="Path 328" d="M676.72,517.57l52.25,1V509.9l-52.25-1Z" fill="#3f3d56"/>
|
|
||||||
<path id="Path_329" data-name="Path 329" d="M534.13,486.79c.08,7-3.16,13.6-5.91,20.07a163.491,163.491,0,0,0-12.66,74.71c.73,11,2.58,22,.73,32.9s-8.43,21.77-19,24.9c17.53,10.45,41.26,9.35,57.76-2.66,8.79-6.4,15.34-15.33,21.75-24.11a97.86,97.86,0,0,1-13.31,44.75A103.43,103.43,0,0,0,637,616.53c4.31-5.81,8.06-12.19,9.72-19.23,3.09-13-1.22-26.51-4.51-39.5a266.055,266.055,0,0,1-6.17-33c-.43-3.56-.78-7.22.1-10.7,1-4.07,3.67-7.51,5.64-11.22,5.6-10.54,5.73-23.3,2.86-34.88s-8.49-22.26-14.06-32.81c-4.46-8.46-9.3-17.31-17.46-22.28-5.1-3.1-11-4.39-16.88-5.64l-25.37-5.43c-5.55-1.19-11.26-2.38-16.87-1.51-9.47,1.48-16.14,8.32-22,15.34-4.59,5.46-15.81,15.71-16.6,22.86-.72,6.59,5.1,17.63,6.09,24.58,1.3,9,2.22,6,7.3,11.52C532,478.05,534.07,482,534.13,486.79Z" transform="translate(-79.34 -172.91)" fill="#3f3d56"/>
|
|
||||||
</g>
|
|
||||||
<g id="docusaurus_keytar" transform="translate(670.271 615.768)">
|
|
||||||
<path id="Path_40" data-name="Path 40" d="M99,52h43.635V69.662H99Z" transform="translate(-49.132 -33.936)" fill="#fff" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_41" data-name="Path 41" d="M13.389,158.195A10.377,10.377,0,0,1,4.4,153a10.377,10.377,0,0,0,8.988,15.584H23.779V158.195Z" transform="translate(-3 -82.47)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_42" data-name="Path 42" d="M66.967,38.083l36.373-2.273V30.615A10.389,10.389,0,0,0,92.95,20.226H46.2l-1.3-2.249a1.5,1.5,0,0,0-2.6,0L41,20.226l-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-1.3-2.249a1.5,1.5,0,0,0-2.6,0l-1.3,2.249-.034,0-2.152-2.151a1.5,1.5,0,0,0-2.508.672L25.21,21.4l-2.7-.723a1.5,1.5,0,0,0-1.836,1.837l.722,2.7-2.65.71a1.5,1.5,0,0,0-.673,2.509l2.152,2.152c0,.011,0,.022,0,.033l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6L20.226,41l-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3-2.249,1.3a1.5,1.5,0,0,0,0,2.6l2.249,1.3A10.389,10.389,0,0,0,30.615,103.34H92.95A10.389,10.389,0,0,0,103.34,92.95V51.393L66.967,49.12a5.53,5.53,0,0,1,0-11.038" transform="translate(-9.836 -17.226)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_43" data-name="Path 43" d="M143,163.779h15.584V143H143Z" transform="translate(-70.275 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_44" data-name="Path 44" d="M173.779,148.389a2.582,2.582,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-75.08 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_45" data-name="Path 45" d="M153,113.389h15.584V103H153Z" transform="translate(-75.08 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_46" data-name="Path 46" d="M183.389,108.944a1.3,1.3,0,1,0,0-2.6,1.336,1.336,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.337,1.337,0,0,0,.166.017" transform="translate(-84.691 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_47" data-name="Path 47" d="M52.188,48.292a1.3,1.3,0,0,1-1.3-1.3,3.9,3.9,0,0,0-7.792,0,1.3,1.3,0,1,1-2.6,0,6.493,6.493,0,0,1,12.987,0,1.3,1.3,0,0,1-1.3,1.3" transform="translate(-21.02 -28.41)" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_48" data-name="Path 48" d="M103,139.752h31.168a10.389,10.389,0,0,0,10.389-10.389V93H113.389A10.389,10.389,0,0,0,103,103.389Z" transform="translate(-51.054 -53.638)" fill="#ffff50" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_49" data-name="Path 49" d="M141.1,94.017H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0-25.877H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.293H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m0,10.389H115.106a.519.519,0,1,1,0-1.039H141.1a.519.519,0,0,1,0,1.039m7.782-47.993c-.006,0-.011,0-.018,0-1.605.055-2.365,1.66-3.035,3.077-.7,1.48-1.24,2.443-2.126,2.414-.981-.035-1.542-1.144-2.137-2.317-.683-1.347-1.462-2.876-3.1-2.819-1.582.054-2.344,1.451-3.017,2.684-.715,1.313-1.2,2.112-2.141,2.075-1-.036-1.533-.938-2.149-1.981-.686-1.162-1.479-2.467-3.084-2.423-1.555.053-2.319,1.239-2.994,2.286-.713,1.106-1.213,1.781-2.164,1.741-1.025-.036-1.554-.784-2.167-1.65-.688-.973-1.463-2.074-3.062-2.021a3.815,3.815,0,0,0-2.959,1.879c-.64.812-1.14,1.456-2.2,1.415a.52.52,0,0,0-.037,1.039,3.588,3.588,0,0,0,3.05-1.811c.611-.777,1.139-1.448,2.178-1.483,1-.043,1.47.579,2.179,1.582.674.953,1.438,2.033,2.977,2.089,1.612.054,2.387-1.151,3.074-2.217.614-.953,1.144-1.775,2.156-1.81.931-.035,1.438.7,2.153,1.912.674,1.141,1.437,2.434,3.006,2.491,1.623.056,2.407-1.361,3.09-2.616.592-1.085,1.15-2.109,2.14-2.143.931-.022,1.417.829,2.135,2.249.671,1.326,1.432,2.828,3.026,2.886l.088,0c1.592,0,2.347-1.6,3.015-3.01.592-1.252,1.152-2.431,2.113-2.479Z" transform="translate(-55.378 -38.552)" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_50" data-name="Path 50" d="M83,163.779h20.779V143H83Z" transform="translate(-41.443 -77.665)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<g id="Group_8" data-name="Group 8" transform="matrix(0.966, -0.259, 0.259, 0.966, 51.971, 43.3)">
|
|
||||||
<rect id="Rectangle_3" data-name="Rectangle 3" width="43.906" height="17.333" rx="2" transform="translate(0 0)" fill="#d8d8d8"/>
|
|
||||||
<g id="Group_2" data-name="Group 2" transform="translate(0.728 10.948)">
|
|
||||||
<rect id="Rectangle_4" data-name="Rectangle 4" width="2.537" height="2.537" rx="1" transform="translate(7.985 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_5" data-name="Rectangle 5" width="2.537" height="2.537" rx="1" transform="translate(10.991 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_6" data-name="Rectangle 6" width="2.537" height="2.537" rx="1" transform="translate(13.997 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_7" data-name="Rectangle 7" width="2.537" height="2.537" rx="1" transform="translate(17.003 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_8" data-name="Rectangle 8" width="2.537" height="2.537" rx="1" transform="translate(20.009 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_9" data-name="Rectangle 9" width="2.537" height="2.537" rx="1" transform="translate(23.015 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_10" data-name="Rectangle 10" width="2.537" height="2.537" rx="1" transform="translate(26.021 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_11" data-name="Rectangle 11" width="2.537" height="2.537" rx="1" transform="translate(29.028 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_12" data-name="Rectangle 12" width="2.537" height="2.537" rx="1" transform="translate(32.034 0)" fill="#4a4a4a"/>
|
|
||||||
<path id="Path_51" data-name="Path 51" d="M.519,0H6.9A.519.519,0,0,1,7.421.52v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0ZM35.653,0h6.383a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H35.652a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,35.652,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group_3" data-name="Group 3" transform="translate(0.728 4.878)">
|
|
||||||
<path id="Path_52" data-name="Path 52" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
<rect id="Rectangle_13" data-name="Rectangle 13" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_14" data-name="Rectangle 14" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_15" data-name="Rectangle 15" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_16" data-name="Rectangle 16" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_17" data-name="Rectangle 17" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_18" data-name="Rectangle 18" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_19" data-name="Rectangle 19" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_20" data-name="Rectangle 20" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_21" data-name="Rectangle 21" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_22" data-name="Rectangle 22" width="2.537" height="2.537" rx="1" transform="translate(31 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_23" data-name="Rectangle 23" width="2.537" height="2.537" rx="1" transform="translate(34.006 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_24" data-name="Rectangle 24" width="2.537" height="2.537" rx="1" transform="translate(37.012 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_25" data-name="Rectangle 25" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group_4" data-name="Group 4" transform="translate(43.283 4.538) rotate(180)">
|
|
||||||
<path id="Path_53" data-name="Path 53" d="M.519,0H2.956a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.519A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
<rect id="Rectangle_26" data-name="Rectangle 26" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_27" data-name="Rectangle 27" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_28" data-name="Rectangle 28" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_29" data-name="Rectangle 29" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_30" data-name="Rectangle 30" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_31" data-name="Rectangle 31" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_32" data-name="Rectangle 32" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_33" data-name="Rectangle 33" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_34" data-name="Rectangle 34" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_35" data-name="Rectangle 35" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_36" data-name="Rectangle 36" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_37" data-name="Rectangle 37" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_38" data-name="Rectangle 38" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_39" data-name="Rectangle 39" width="2.537" height="2.537" rx="1" transform="translate(3.945 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_40" data-name="Rectangle 40" width="2.537" height="2.537" rx="1" transform="translate(6.951 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_41" data-name="Rectangle 41" width="2.537" height="2.537" rx="1" transform="translate(9.958 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_42" data-name="Rectangle 42" width="2.537" height="2.537" rx="1" transform="translate(12.964 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_43" data-name="Rectangle 43" width="2.537" height="2.537" rx="1" transform="translate(15.97 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_44" data-name="Rectangle 44" width="2.537" height="2.537" rx="1" transform="translate(18.976 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_45" data-name="Rectangle 45" width="2.537" height="2.537" rx="1" transform="translate(21.982 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_46" data-name="Rectangle 46" width="2.537" height="2.537" rx="1" transform="translate(24.988 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_47" data-name="Rectangle 47" width="2.537" height="2.537" rx="1" transform="translate(27.994 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_48" data-name="Rectangle 48" width="2.537" height="2.537" rx="1" transform="translate(31.001 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_49" data-name="Rectangle 49" width="2.537" height="2.537" rx="1" transform="translate(34.007 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_50" data-name="Rectangle 50" width="2.537" height="2.537" rx="1" transform="translate(37.013 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_51" data-name="Rectangle 51" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group_6" data-name="Group 6" transform="translate(0.728 7.883)">
|
|
||||||
<path id="Path_54" data-name="Path 54" d="M.519,0h3.47a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(0 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
<g id="Group_5" data-name="Group 5" transform="translate(5.073 0)">
|
|
||||||
<rect id="Rectangle_52" data-name="Rectangle 52" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_53" data-name="Rectangle 53" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_54" data-name="Rectangle 54" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_55" data-name="Rectangle 55" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_56" data-name="Rectangle 56" width="2.537" height="2.537" rx="1" transform="translate(12.025 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_57" data-name="Rectangle 57" width="2.537" height="2.537" rx="1" transform="translate(15.031 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_58" data-name="Rectangle 58" width="2.537" height="2.537" rx="1" transform="translate(18.037 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_59" data-name="Rectangle 59" width="2.537" height="2.537" rx="1" transform="translate(21.042 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_60" data-name="Rectangle 60" width="2.537" height="2.537" rx="1" transform="translate(24.049 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_61" data-name="Rectangle 61" width="2.537" height="2.537" rx="1" transform="translate(27.055 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_62" data-name="Rectangle 62" width="2.537" height="2.537" rx="1" transform="translate(30.061 0)" fill="#4a4a4a"/>
|
|
||||||
</g>
|
|
||||||
<path id="Path_55" data-name="Path 55" d="M.52,0H3.8a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.017V.52A.519.519,0,0,1,.519,0Z" transform="translate(38.234 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
</g>
|
|
||||||
<g id="Group_7" data-name="Group 7" transform="translate(0.728 14.084)">
|
|
||||||
<rect id="Rectangle_63" data-name="Rectangle 63" width="2.537" height="2.537" rx="1" transform="translate(0 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_64" data-name="Rectangle 64" width="2.537" height="2.537" rx="1" transform="translate(3.006 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_65" data-name="Rectangle 65" width="2.537" height="2.537" rx="1" transform="translate(6.012 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_66" data-name="Rectangle 66" width="2.537" height="2.537" rx="1" transform="translate(9.018 0)" fill="#4a4a4a"/>
|
|
||||||
<path id="Path_56" data-name="Path 56" d="M.519,0H14.981A.519.519,0,0,1,15.5.519v1.5a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,2.018V.519A.519.519,0,0,1,.519,0Zm15.97,0h1.874a.519.519,0,0,1,.519.519v1.5a.519.519,0,0,1-.519.519H16.489a.519.519,0,0,1-.519-.519V.519A.519.519,0,0,1,16.489,0Z" transform="translate(12.024 0)" fill="#4a4a4a" fill-rule="evenodd"/>
|
|
||||||
<rect id="Rectangle_67" data-name="Rectangle 67" width="2.537" height="2.537" rx="1" transform="translate(31.376 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_68" data-name="Rectangle 68" width="2.537" height="2.537" rx="1" transform="translate(34.382 0)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_69" data-name="Rectangle 69" width="2.537" height="2.537" rx="1" transform="translate(40.018 0)" fill="#4a4a4a"/>
|
|
||||||
<path id="Path_57" data-name="Path 57" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(39.736 1.08) rotate(180)" fill="#4a4a4a"/>
|
|
||||||
<path id="Path_58" data-name="Path 58" d="M2.537,0V.561a.519.519,0,0,1-.519.519H.519A.519.519,0,0,1,0,.561V0Z" transform="translate(37.2 1.456)" fill="#4a4a4a"/>
|
|
||||||
</g>
|
|
||||||
<rect id="Rectangle_70" data-name="Rectangle 70" width="42.273" height="1.127" rx="0.564" transform="translate(0.915 0.556)" fill="#4a4a4a"/>
|
|
||||||
<rect id="Rectangle_71" data-name="Rectangle 71" width="2.37" height="0.752" rx="0.376" transform="translate(1.949 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_72" data-name="Rectangle 72" width="2.37" height="0.752" rx="0.376" transform="translate(5.193 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_73" data-name="Rectangle 73" width="2.37" height="0.752" rx="0.376" transform="translate(7.688 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_74" data-name="Rectangle 74" width="2.37" height="0.752" rx="0.376" transform="translate(10.183 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_75" data-name="Rectangle 75" width="2.37" height="0.752" rx="0.376" transform="translate(12.679 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_76" data-name="Rectangle 76" width="2.37" height="0.752" rx="0.376" transform="translate(15.797 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_77" data-name="Rectangle 77" width="2.37" height="0.752" rx="0.376" transform="translate(18.292 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_78" data-name="Rectangle 78" width="2.37" height="0.752" rx="0.376" transform="translate(20.788 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_79" data-name="Rectangle 79" width="2.37" height="0.752" rx="0.376" transform="translate(23.283 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_80" data-name="Rectangle 80" width="2.37" height="0.752" rx="0.376" transform="translate(26.402 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_81" data-name="Rectangle 81" width="2.37" height="0.752" rx="0.376" transform="translate(28.897 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_82" data-name="Rectangle 82" width="2.37" height="0.752" rx="0.376" transform="translate(31.393 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_83" data-name="Rectangle 83" width="2.37" height="0.752" rx="0.376" transform="translate(34.512 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_84" data-name="Rectangle 84" width="2.37" height="0.752" rx="0.376" transform="translate(37.007 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
<rect id="Rectangle_85" data-name="Rectangle 85" width="2.37" height="0.752" rx="0.376" transform="translate(39.502 0.744)" fill="#d8d8d8" opacity="0.136"/>
|
|
||||||
</g>
|
|
||||||
<path id="Path_59" data-name="Path 59" d="M123.779,148.389a2.583,2.583,0,0,0-.332.033c-.02-.078-.038-.156-.06-.234a2.594,2.594,0,1,0-2.567-4.455q-.086-.088-.174-.175a2.593,2.593,0,1,0-4.461-2.569c-.077-.022-.154-.04-.231-.06a2.6,2.6,0,1,0-5.128,0c-.077.02-.154.038-.231.06a2.594,2.594,0,1,0-4.461,2.569,10.384,10.384,0,1,0,17.314,9.992,2.592,2.592,0,1,0,.332-5.161" transform="translate(-51.054 -75.262)" fill="#44d860" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_60" data-name="Path 60" d="M83,113.389h20.779V103H83Z" transform="translate(-41.443 -58.444)" fill="#3ecc5f" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_61" data-name="Path 61" d="M123.389,108.944a1.3,1.3,0,1,0,0-2.6,1.338,1.338,0,0,0-.166.017c-.01-.039-.019-.078-.03-.117a1.3,1.3,0,0,0-.5-2.5,1.285,1.285,0,0,0-.783.269q-.043-.044-.087-.087a1.285,1.285,0,0,0,.263-.776,1.3,1.3,0,0,0-2.493-.509,5.195,5.195,0,1,0,0,10,1.3,1.3,0,0,0,2.493-.509,1.285,1.285,0,0,0-.263-.776q.044-.043.087-.087a1.285,1.285,0,0,0,.783.269,1.3,1.3,0,0,0,.5-2.5c.011-.038.02-.078.03-.117a1.335,1.335,0,0,0,.166.017" transform="translate(-55.859 -57.894)" fill="#44d860" fill-rule="evenodd"/>
|
|
||||||
<path id="Path_62" data-name="Path 62" d="M141.8,38.745a1.41,1.41,0,0,1-.255-.026,1.309,1.309,0,0,1-.244-.073,1.349,1.349,0,0,1-.224-.119,1.967,1.967,0,0,1-.2-.161,1.52,1.52,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.41,1.41,0,0,1,.026-.255,1.5,1.5,0,0,1,.072-.244,1.364,1.364,0,0,1,.12-.223,1.252,1.252,0,0,1,.358-.358,1.349,1.349,0,0,1,.224-.119,1.309,1.309,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.968,1.968,0,0,1,.2.161,1.908,1.908,0,0,1,.161.2,1.322,1.322,0,0,1,.12.223,1.361,1.361,0,0,1,.1.5,1.317,1.317,0,0,1-.379.919,1.968,1.968,0,0,1-.2.161,1.346,1.346,0,0,1-.223.119,1.332,1.332,0,0,1-.5.1m10.389-.649a1.326,1.326,0,0,1-.92-.379,1.979,1.979,0,0,1-.161-.2,1.282,1.282,0,0,1-.218-.722,1.326,1.326,0,0,1,.379-.919,1.967,1.967,0,0,1,.2-.161,1.351,1.351,0,0,1,.224-.119,1.308,1.308,0,0,1,.244-.073,1.2,1.2,0,0,1,.509,0,1.262,1.262,0,0,1,.468.192,1.967,1.967,0,0,1,.2.161,1.326,1.326,0,0,1,.379.919,1.461,1.461,0,0,1-.026.255,1.323,1.323,0,0,1-.073.244,1.847,1.847,0,0,1-.119.223,1.911,1.911,0,0,1-.161.2,1.967,1.967,0,0,1-.2.161,1.294,1.294,0,0,1-.722.218" transform="translate(-69.074 -26.006)" fill-rule="evenodd"/>
|
|
||||||
</g>
|
|
||||||
<g id="React-icon" transform="translate(906.3 541.56)">
|
|
||||||
<path id="Path_330" data-name="Path 330" d="M263.668,117.179c0-5.827-7.3-11.35-18.487-14.775,2.582-11.4,1.434-20.477-3.622-23.382a7.861,7.861,0,0,0-4.016-1v4a4.152,4.152,0,0,1,2.044.466c2.439,1.4,3.5,6.724,2.672,13.574-.2,1.685-.52,3.461-.914,5.272a86.9,86.9,0,0,0-11.386-1.954,87.469,87.469,0,0,0-7.459-8.965c5.845-5.433,11.332-8.41,15.062-8.41V78h0c-4.931,0-11.386,3.514-17.913,9.611-6.527-6.061-12.982-9.539-17.913-9.539v4c3.712,0,9.216,2.959,15.062,8.356a84.687,84.687,0,0,0-7.405,8.947,83.732,83.732,0,0,0-11.4,1.972c-.412-1.793-.717-3.532-.932-5.2-.843-6.85.2-12.175,2.618-13.592a3.991,3.991,0,0,1,2.062-.466v-4h0a8,8,0,0,0-4.052,1c-5.039,2.9-6.168,11.96-3.568,23.328-11.153,3.443-18.415,8.947-18.415,14.757,0,5.828,7.3,11.35,18.487,14.775-2.582,11.4-1.434,20.477,3.622,23.382a7.882,7.882,0,0,0,4.034,1c4.931,0,11.386-3.514,17.913-9.611,6.527,6.061,12.982,9.539,17.913,9.539a8,8,0,0,0,4.052-1c5.039-2.9,6.168-11.96,3.568-23.328C256.406,128.511,263.668,122.988,263.668,117.179Zm-23.346-11.96c-.663,2.313-1.488,4.7-2.421,7.083-.735-1.434-1.506-2.869-2.349-4.3-.825-1.434-1.7-2.833-2.582-4.2C235.517,104.179,237.974,104.645,240.323,105.219Zm-8.212,19.1c-1.4,2.421-2.833,4.716-4.321,6.85-2.672.233-5.379.359-8.1.359-2.708,0-5.415-.126-8.069-.341q-2.232-3.2-4.339-6.814-2.044-3.523-3.73-7.136c1.112-2.4,2.367-4.805,3.712-7.154,1.4-2.421,2.833-4.716,4.321-6.85,2.672-.233,5.379-.359,8.1-.359,2.708,0,5.415.126,8.069.341q2.232,3.2,4.339,6.814,2.044,3.523,3.73,7.136C234.692,119.564,233.455,121.966,232.11,124.315Zm5.792-2.331c.968,2.4,1.793,4.805,2.474,7.136-2.349.574-4.823,1.058-7.387,1.434.879-1.381,1.757-2.8,2.582-4.25C236.4,124.871,237.167,123.419,237.9,121.984ZM219.72,141.116a73.921,73.921,0,0,1-4.985-5.738c1.614.072,3.263.126,4.931.126,1.685,0,3.353-.036,4.985-.126A69.993,69.993,0,0,1,219.72,141.116ZM206.38,130.555c-2.546-.377-5-.843-7.352-1.417.663-2.313,1.488-4.7,2.421-7.083.735,1.434,1.506,2.869,2.349,4.3S205.5,129.192,206.38,130.555ZM219.63,93.241a73.924,73.924,0,0,1,4.985,5.738c-1.614-.072-3.263-.126-4.931-.126-1.686,0-3.353.036-4.985.126A69.993,69.993,0,0,1,219.63,93.241ZM206.362,103.8c-.879,1.381-1.757,2.8-2.582,4.25-.825,1.434-1.6,2.869-2.331,4.3-.968-2.4-1.793-4.805-2.474-7.136C201.323,104.663,203.8,104.179,206.362,103.8Zm-16.227,22.449c-6.348-2.708-10.454-6.258-10.454-9.073s4.106-6.383,10.454-9.073c1.542-.663,3.228-1.255,4.967-1.811a86.122,86.122,0,0,0,4.034,10.92,84.9,84.9,0,0,0-3.981,10.866C193.38,127.525,191.694,126.915,190.134,126.252Zm9.647,25.623c-2.439-1.4-3.5-6.724-2.672-13.574.2-1.686.52-3.461.914-5.272a86.9,86.9,0,0,0,11.386,1.954,87.465,87.465,0,0,0,7.459,8.965c-5.845,5.433-11.332,8.41-15.062,8.41A4.279,4.279,0,0,1,199.781,151.875Zm42.532-13.663c.843,6.85-.2,12.175-2.618,13.592a3.99,3.99,0,0,1-2.062.466c-3.712,0-9.216-2.959-15.062-8.356a84.689,84.689,0,0,0,7.405-8.947,83.731,83.731,0,0,0,11.4-1.972A50.194,50.194,0,0,1,242.313,138.212Zm6.9-11.96c-1.542.663-3.228,1.255-4.967,1.811a86.12,86.12,0,0,0-4.034-10.92,84.9,84.9,0,0,0,3.981-10.866c1.775.556,3.461,1.165,5.039,1.829,6.348,2.708,10.454,6.258,10.454,9.073C259.67,119.994,255.564,123.562,249.216,126.252Z" fill="#61dafb"/>
|
|
||||||
<path id="Path_331" data-name="Path 331" d="M320.8,78.4Z" transform="translate(-119.082 -0.328)" fill="#61dafb"/>
|
|
||||||
<circle id="Ellipse_112" data-name="Ellipse 112" cx="8.194" cy="8.194" r="8.194" transform="translate(211.472 108.984)" fill="#61dafb"/>
|
|
||||||
<path id="Path_332" data-name="Path 332" d="M520.5,78.1Z" transform="translate(-282.975 -0.082)" fill="#61dafb"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 12 KiB |