eerge remote-tracking branch 'origin/develop' into ts-property

This commit is contained in:
Quinn Dougherty 2022-04-20 16:58:51 -04:00
commit a5cb34ff7f
13 changed files with 332 additions and 65 deletions

View File

@ -18,13 +18,6 @@ on:
- production - production
- staging - staging
- develop - develop
pull_request:
# The branches below must be a subset of the branches above
branches:
- master
- production
- staging
- develop
schedule: schedule:
- cron: "42 19 * * 0" - cron: "42 19 * * 0"

View File

@ -1,6 +0,0 @@
{
"extends": "@parcel/config-default",
"transformers": {
"*.res": ["@parcel/transformer-raw"]
}
}

View File

@ -2,3 +2,5 @@ dist
lib lib
*.bs.js *.bs.js
*.gen.tsx *.gen.tsx
.nyc_output/
coverage/

View File

@ -86,7 +86,9 @@ module Exponential = {
module Cauchy = { module Cauchy = {
type t = cauchy type t = cauchy
let make = (local, scale): symbolicDist => #Cauchy({local: local, scale: scale}) let make = (local, scale): result<symbolicDist, string> => Ok(
#Cauchy({local: local, scale: scale}),
)
let pdf = (x, t: t) => Jstat.Cauchy.pdf(x, t.local, t.scale) let pdf = (x, t: t) => Jstat.Cauchy.pdf(x, t.local, t.scale)
let cdf = (x, t: t) => Jstat.Cauchy.cdf(x, t.local, t.scale) let cdf = (x, t: t) => Jstat.Cauchy.cdf(x, t.local, t.scale)
let inv = (p, t: t) => Jstat.Cauchy.inv(p, t.local, t.scale) let inv = (p, t: t) => Jstat.Cauchy.inv(p, t.local, t.scale)

View File

@ -44,7 +44,7 @@ let defaultBindings: T.bindings = Belt.Map.String.empty
/* /*
Recursively evaluate/reduce the expression (Lisp AST) Recursively evaluate/reduce the expression (Lisp AST)
*/ */
let rec reduceExpression = (expression: t, bindings: T.bindings): result<expressionValue, 'e> => { let reduceExpression = (expression: t, bindings: T.bindings): result<expressionValue, 'e> => {
/* /*
After reducing each level of expression(Lisp AST), we have a value list to evaluate After reducing each level of expression(Lisp AST), we have a value list to evaluate
*/ */
@ -135,6 +135,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result<express
) )
racc->Result.flatMap(acc => acc->doMacroCall(bindings)) racc->Result.flatMap(acc => acc->doMacroCall(bindings))
} }
| T.EBindings(bindings) => T.EBindings(bindings)->Ok
} }
let rec reduceExpandedExpression = (expression: t): result<expressionValue, 'e> => let rec reduceExpandedExpression = (expression: t): result<expressionValue, 'e> =>
@ -155,6 +156,7 @@ let rec reduceExpression = (expression: t, bindings: T.bindings): result<express
) )
racc->Result.flatMap(acc => acc->reduceValueList) racc->Result.flatMap(acc => acc->reduceValueList)
} }
| T.EBindings(bindings) => RETodo("Cannot return bindings")->Error
} }
let rExpandedExpression: result<t, 'e> = expression->seekMacros(bindings) let rExpandedExpression: result<t, 'e> = expression->seekMacros(bindings)

View File

@ -149,6 +149,7 @@ module SymbolicConstructors = {
| "uniform" => Ok(SymbolicDist.Uniform.make) | "uniform" => Ok(SymbolicDist.Uniform.make)
| "beta" => Ok(SymbolicDist.Beta.make) | "beta" => Ok(SymbolicDist.Beta.make)
| "lognormal" => Ok(SymbolicDist.Lognormal.make) | "lognormal" => Ok(SymbolicDist.Lognormal.make)
| "cauchy" => Ok(SymbolicDist.Cauchy.make)
| "to" => Ok(SymbolicDist.From90thPercentile.make) | "to" => Ok(SymbolicDist.From90thPercentile.make)
| _ => Error("Unreachable state") | _ => Error("Unreachable state")
} }
@ -182,7 +183,7 @@ let dispatchToGenericOutput = (call: ExpressionValue.functionCall): option<
->E.R.bind(r => r(f1)) ->E.R.bind(r => r(f1))
->SymbolicConstructors.symbolicResultToOutput ->SymbolicConstructors.symbolicResultToOutput
| ( | (
("normal" | "uniform" | "beta" | "lognormal" | "to") as fnName, ("normal" | "uniform" | "beta" | "lognormal" | "cauchy" | "to") as fnName,
[EvNumber(f1), EvNumber(f2)], [EvNumber(f1), EvNumber(f2)],
) => ) =>
SymbolicConstructors.twoFloat(fnName) SymbolicConstructors.twoFloat(fnName)

View File

@ -0,0 +1,2 @@
.docusaurus
build

View File

@ -1,12 +1,15 @@
--- ---
title: "Functions Reference"
sidebar_position: 7 sidebar_position: 7
--- ---
import { SquiggleEditor } from "../../src/components/SquiggleEditor"; import { SquiggleEditor } from "../../src/components/SquiggleEditor";
# Squiggle Functions Reference _The source of truth for this document is [this file of code](https://github.com/quantified-uncertainty/squiggle/blob/develop/packages/squiggle-lang/src/rescript/ReducerInterface/ReducerInterface_GenericDistribution.res)_
## Distributions ## Inventory distributions
We provide starter distributions, computed symbolically.
### Normal distribution ### Normal distribution
@ -15,6 +18,10 @@ and standard deviation.
<SquiggleEditor initialSquiggleString="normal(5, 1)" /> <SquiggleEditor initialSquiggleString="normal(5, 1)" />
#### Validity
- `sd > 0`
### Uniform distribution ### Uniform distribution
The `uniform(low, high)` function creates a uniform distribution between the The `uniform(low, high)` function creates a uniform distribution between the
@ -22,86 +29,281 @@ two given numbers.
<SquiggleEditor initialSquiggleString="uniform(3, 7)" /> <SquiggleEditor initialSquiggleString="uniform(3, 7)" />
#### Validity
- `low < high`
### Lognormal distribution ### Lognormal distribution
The `lognormal(mu, sigma)` returns the log of a normal distribution with parameters The `lognormal(mu, sigma)` returns the log of a normal distribution with parameters
mu and sigma. The log of lognormal(mu, sigma) is a normal distribution with parameters `mu` and `sigma`. The log of `lognormal(mu, sigma)` is a normal distribution with mean `mu` and standard deviation `sigma`.
mean mu and standard deviation sigma.
<SquiggleEditor initialSquiggleString="lognormal(0, 0.7)" /> <SquiggleEditor initialSquiggleString="lognormal(0, 0.7)" />
An alternative format is also available. The "to" notation creates a lognormal An alternative format is also available. The `to` notation creates a lognormal
distribution with a 90% confidence interval between the two numbers. We add distribution with a 90% confidence interval between the two numbers. We add
this convinience as lognormal distributions are commonly used in practice. this convenience as lognormal distributions are commonly used in practice.
<SquiggleEditor initialSquiggleString="2 to 10" /> <SquiggleEditor initialSquiggleString="2 to 10" />
#### Future feature:
Furthermore, it's also possible to create a lognormal from it's actual mean Furthermore, it's also possible to create a lognormal from it's actual mean
and standard deviation, using `lognormalFromMeanAndStdDev`. and standard deviation, using `lognormalFromMeanAndStdDev`.
TODO: interpreter/parser doesn't provide this in current `develop` branch
<SquiggleEditor initialSquiggleString="lognormalFromMeanAndStdDev(20, 10)" /> <SquiggleEditor initialSquiggleString="lognormalFromMeanAndStdDev(20, 10)" />
#### Validity
- `sigma > 0`
- In `x to y` notation, `x < y`
### Beta distribution ### Beta distribution
The `beta(a, b)` function creates a beta distribution with parameters a and b: The `beta(a, b)` function creates a beta distribution with parameters `a` and `b`:
<SquiggleEditor initialSquiggleString="beta(20, 20)" /> <SquiggleEditor initialSquiggleString="beta(10, 20)" />
#### Validity
- `a > 0`
- `b > 0`
- Empirically, we have noticed that numerical instability arises when `a < 1` or `b < 1`
### Exponential distribution ### Exponential distribution
The `exponential(mean)` function creates an exponential distribution with the given The `exponential(rate)` function creates an exponential distribution with the given
mean. rate.
<SquiggleEditor initialSquiggleString="exponential(1)" /> <SquiggleEditor initialSquiggleString="exponential(1.11)" />
### The Triangular distribution #### Validity
- `rate > 0`
### Triangular distribution
The `triangular(a,b,c)` function creates a triangular distribution with lower The `triangular(a,b,c)` function creates a triangular distribution with lower
bound a, mode b and upper bound c. bound `a`, mode `b` and upper bound `c`.
#### Validity
- `a < b < c`
<SquiggleEditor initialSquiggleString="triangular(1, 2, 4)" /> <SquiggleEditor initialSquiggleString="triangular(1, 2, 4)" />
### Multimodal distriutions ### Scalar (constant dist)
The multimodal function combines 2 or more other distributions to create a weighted Squiggle, when the context is right, automatically casts a float to a constant distribution.
## Operating on distributions
Here are the ways we combine distributions.
### Mixture of distributions
The `mixture` function combines 2 or more other distributions to create a weighted
combination of the two. The first positional arguments represent the distributions combination of the two. The first positional arguments represent the distributions
to be combined, and the last argument is how much to weigh every distribution in the to be combined, and the last argument is how much to weigh every distribution in the
combination. combination.
<SquiggleEditor initialSquiggleString="mx(uniform(0,1), normal(1,1), [0.5, 0.5])" /> <SquiggleEditor initialSquiggleString="mixture(uniform(0,1), normal(1,1), [0.5, 0.5])" />
It's possible to create discrete distributions using this method. It's possible to create discrete distributions using this method.
<SquiggleEditor initialSquiggleString="mx(0, 1, [0.2,0.8])" /> <SquiggleEditor initialSquiggleString="mixture(0, 1, [0.2,0.8])" />
As well as mixed distributions: As well as mixed distributions:
<SquiggleEditor initialSquiggleString="mx(3, 8, 1 to 10, [0.2, 0.3, 0.5])" /> <SquiggleEditor initialSquiggleString="mixture(3, 8, 1 to 10, [0.2, 0.3, 0.5])" />
## Other Functions An alias of `mixture` is `mx`
### PDF of a distribution #### Validity
The `pdf(distribution, x)` function returns the density of a distribution at the Using javascript's variable arguments notation, consider `mx(...dists, weights)`:
- `dists.length == weights.length`
### Addition
A horizontal right shift
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 + dist2`}
/>
### Subtraction
A horizontal left shift
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 - dist2`}
/>
### Multiplication
TODO: provide intuition pump for the semantics
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 * dist2`}
/>
We also provide concatenation of two distributions as a syntax sugar for `*`
<SquiggleEditor initialSquiggleString="(0.1 to 1) triangular(1,2,3)" />
### Division
TODO: provide intuition pump for the semantics
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 / dist2`}
/>
### Exponentiation
TODO: provide intuition pump for the semantics
<SquiggleEditor initialSquiggleString={`(0.1 to 1) ^ beta(2, 3)`} />
### Taking the base `e` exponential
<SquiggleEditor
initialSquiggleString={`dist = triangular(1,2,3)
exp(dist)`}
/>
### Taking logarithms
<SquiggleEditor
initialSquiggleString={`dist = triangular(1,2,3)
log(dist)`}
/>
<SquiggleEditor
initialSquiggleString={`dist = beta(1,2)
log10(dist)`}
/>
Base `x`
<SquiggleEditor
initialSquiggleString={`x = 2
dist = beta(2,3)
log(dist, x)`}
/>
#### Validity
- `x` must be a scalar
- See [the current discourse](https://github.com/quantified-uncertainty/squiggle/issues/304)
### Pointwise addition
**Pointwise operations are done with `PointSetDist` internals rather than `SampleSetDist` internals**.
TODO: this isn't in the new interpreter/parser yet.
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 .+ dist2`}
/>
### Pointwise subtraction
TODO: this isn't in the new interpreter/parser yet.
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 .- dist2`}
/>
### Pointwise multiplication
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 .* dist2`}
/>
### Pointwise division
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 ./ dist2`}
/>
### Pointwise exponentiation
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dist1 .^ dist2`}
/>
### Pointwise logarithm
TODO: write about the semantics and the case handling re scalar vs. dist and log base.
<SquiggleEditor
initialSquiggleString={`dist1 = 1 to 10
dist2 = triangular(1,2,3)
dotLog(dist1, dist2)`}
/>
## Standard functions on distributions
### Probability density function
The `pdf(dist, x)` function returns the density of a distribution at the
given point x. given point x.
<SquiggleEditor initialSquiggleString="pdf(normal(0,1),0)" /> <SquiggleEditor initialSquiggleString="pdf(normal(0,1),0)" />
### Inverse of a distribution #### Validity
The `inv(distribution, prob)` gives the value x or which the probability for all values - `x` must be a scalar
lower than x is equal to prob. It is the inverse of `cdf`. - `dist` must be a distribution
<SquiggleEditor initialSquiggleString="inv(normal(0,1),0.5)" /> ### Cumulative density function
### CDF of a distribution The `cdf(dist, x)` gives the cumulative probability of the distribution
The `cdf(distribution,x)` gives the cumulative probability of the distribution
or all values lower than x. It is the inverse of `inv`. or all values lower than x. It is the inverse of `inv`.
<SquiggleEditor initialSquiggleString="cdf(normal(0,1),0)" /> <SquiggleEditor initialSquiggleString="cdf(normal(0,1),0)" />
### Mean of a distribution #### Validity
- `x` must be a scalar
- `dist` must be a distribution
### Inverse CDF
The `inv(dist, prob)` gives the value x or which the probability for all values
lower than x is equal to prob. It is the inverse of `cdf`.
<SquiggleEditor initialSquiggleString="inv(normal(0,1),0.5)" />
#### Validity
- `prob` must be a scalar (please only put it in `(0,1)`)
- `dist` must be a distribution
### Mean
The `mean(distribution)` function gives the mean (expected value) of a distribution. The `mean(distribution)` function gives the mean (expected value) of a distribution.
@ -112,3 +314,55 @@ The `mean(distribution)` function gives the mean (expected value) of a distribut
The `sample(distribution)` samples a given distribution. The `sample(distribution)` samples a given distribution.
<SquiggleEditor initialSquiggleString="sample(normal(0, 10))" /> <SquiggleEditor initialSquiggleString="sample(normal(0, 10))" />
## Normalization
Some distribution operations (like horizontal shift) return an unnormalized distriibution.
We provide a `normalize` function
<SquiggleEditor initialSquiggleString="normalize((0.1 to 1) + triangular(0.1, 1, 10))" />
#### Validity - Input to `normalize` must be a dist
We provide a predicate `isNormalized`, for when we have simple control flow
<SquiggleEditor initialSquiggleString="isNormalized((0.1 to 1) * triangular(0.1, 1, 10))" />
#### Validity
- Input to `isNormalized` must be a dist
## Convert any distribution to a sample set distribution
`toSampleSet` has two signatures
It is unary when you use an internal hardcoded number of samples
<SquiggleEditor initialSquiggleString="toSampleSet(0.1 to 1)" />
And binary when you provide a number of samples (floored)
<SquiggleEditor initialSquiggleString="toSampleSet(0.1 to 1, 100)" />
## `inspect`
You may like to debug by right clicking your browser and using the _inspect_ functionality on the webpage, and viewing the _console_ tab. Then, wrap your squiggle output with `inspect` to log an internal representation.
<SquiggleEditor initialSquiggleString="inspect(toSampleSet(0.1 to 1, 100))" />
Save for a logging side effect, `inspect` does nothing to input and returns it.
## Truncate
You can cut off from the left
<SquiggleEditor initialSquiggleString="truncateLeft(0.1 to 1, 0.5)" />
You can cut off from the right
<SquiggleEditor initialSquiggleString="truncateRight(0.1 to 1, 10)" />
You can cut off from both sides
<SquiggleEditor initialSquiggleString="truncate(0.1 to 1, 0.5, 1.5)" />

View File

@ -1,5 +1,5 @@
--- ---
title: Statistical properties of algebraic combinations of distributions for property testing. title: Invariants of Probability Distributions
urlcolor: blue urlcolor: blue
author: author:
- Nuño Sempere - Nuño Sempere
@ -7,13 +7,17 @@ author:
abstract: This document outlines some properties about algebraic combinations of distributions. It is meant to facilitate property tests for [Squiggle](https://squiggle-language.com/), an estimation language for forecasters. So far, we are focusing on the means, the standard deviation and the shape of the pdfs. abstract: This document outlines some properties about algebraic combinations of distributions. It is meant to facilitate property tests for [Squiggle](https://squiggle-language.com/), an estimation language for forecasters. So far, we are focusing on the means, the standard deviation and the shape of the pdfs.
--- ---
Invariants to check with property tests.
_This document right now is normative and aspirational, not a description of the testing that's currently done_. _This document right now is normative and aspirational, not a description of the testing that's currently done_.
## Algebraic combinations
The academic keyword to search for in relation to this document is "[algebra of random variables](https://wikiless.org/wiki/Algebra_of_random_variables?lang=en)". Squiggle doesn't yet support getting the standard deviation, denoted by $\sigma$, but such support could yet be added. The academic keyword to search for in relation to this document is "[algebra of random variables](https://wikiless.org/wiki/Algebra_of_random_variables?lang=en)". Squiggle doesn't yet support getting the standard deviation, denoted by $\sigma$, but such support could yet be added.
## Means and standard deviations ### Means and standard deviations
### Sums #### Sums
$$ $$
mean(f+g) = mean(f) + mean(g) mean(f+g) = mean(f) + mean(g)
@ -29,7 +33,7 @@ $$
mean(normal(a,b) + normal(c,d)) = mean(normal(a+c, \sqrt{b^2 + d^2})) mean(normal(a,b) + normal(c,d)) = mean(normal(a+c, \sqrt{b^2 + d^2}))
$$ $$
### Subtractions #### Subtractions
$$ $$
mean(f-g) = mean(f) - mean(g) mean(f-g) = mean(f) - mean(g)
@ -39,7 +43,7 @@ $$
\sigma(f-g) = \sqrt{\sigma(f)^2 + \sigma(g)^2} \sigma(f-g) = \sqrt{\sigma(f)^2 + \sigma(g)^2}
$$ $$
### Multiplications #### Multiplications
$$ $$
mean(f \cdot g) = mean(f) \cdot mean(g) mean(f \cdot g) = mean(f) \cdot mean(g)
@ -49,15 +53,15 @@ $$
\sigma(f \cdot g) = \sqrt{ (\sigma(f)^2 + mean(f)) \cdot (\sigma(g)^2 + mean(g)) - (mean(f) \cdot mean(g))^2} \sigma(f \cdot g) = \sqrt{ (\sigma(f)^2 + mean(f)) \cdot (\sigma(g)^2 + mean(g)) - (mean(f) \cdot mean(g))^2}
$$ $$
### Divisions #### Divisions
Divisions are tricky, and in general we don't have good expressions to characterize properties of ratios. In particular, the ratio of two normals is a Cauchy distribution, which doesn't have to have a mean. Divisions are tricky, and in general we don't have good expressions to characterize properties of ratios. In particular, the ratio of two normals is a Cauchy distribution, which doesn't have to have a mean.
## Probability density functions (pdfs) ### Probability density functions (pdfs)
Specifying the pdf of the sum/multiplication/... of distributions as a function of the pdfs of the individual arguments can still be done. But it requires integration. My sense is that this is still doable, and I (Nuño) provide some _pseudocode_ to do this. Specifying the pdf of the sum/multiplication/... of distributions as a function of the pdfs of the individual arguments can still be done. But it requires integration. My sense is that this is still doable, and I (Nuño) provide some _pseudocode_ to do this.
### Sums #### Sums
Let $f, g$ be two independently distributed functions. Then, the pdf of their sum, evaluated at a point $z$, expressed as $(f + g)(z)$, is given by: Let $f, g$ be two independently distributed functions. Then, the pdf of their sum, evaluated at a point $z$, expressed as $(f + g)(z)$, is given by:
@ -110,15 +114,31 @@ let pdfOfSum = (pdf1, pdf2, cdf1, cdf2, z) => {
}; };
``` ```
## Cumulative density functions ### Cumulative density functions
TODO TODO
## Inverse cumulative density functions ### Inverse cumulative density functions
TODO TODO
# To do: ## `pdf`, `cdf`, and `inv`
With $\forall dist, pdf := x \mapsto \texttt{pdf}(dist, x) \land cdf := x \mapsto \texttt{cdf}(dist, x) \land inv := p \mapsto \texttt{inv}(dist, p)$,
### `cdf` and `inv` are inverses
$$
\forall x \in (0,1), cdf(inv(x)) = x \land \forall x \in \texttt{dom}(cdf), x = inv(cdf(x))
$$
### The codomain of `cdf` equals the open interval `(0,1)` equals the codomain of `pdf`
$$
\texttt{cod}(cdf) = (0,1) = \texttt{cod}(pdf)
$$
## To do:
- Provide sources or derivations, useful as this document becomes more complicated - Provide sources or derivations, useful as this document becomes more complicated
- Provide definitions for the probability density function, exponential, inverse, log, etc. - Provide definitions for the probability density function, exponential, inverse, log, etc.

View File

@ -49,7 +49,7 @@ const config = {
sidebarPath: require.resolve("./sidebars.js"), sidebarPath: require.resolve("./sidebars.js"),
// Please change this to your repo. // Please change this to your repo.
editUrl: editUrl:
"https://github.com/quantified-uncertainty/squiggle/tree/master/packages/website/", "https://github.com/quantified-uncertainty/squiggle/tree/develop/packages/website/",
remarkPlugins: [math], remarkPlugins: [math],
rehypePlugins: [katex], rehypePlugins: [katex],
}, },
@ -57,7 +57,7 @@ const config = {
showReadingTime: true, showReadingTime: true,
// Please change this to your repo. // Please change this to your repo.
editUrl: editUrl:
"https://github.com/quantified-uncertainty/squiggle/tree/master/packages/website/", "https://github.com/quantified-uncertainty/squiggle/tree/develop/packages/website/",
}, },
theme: { theme: {
customCss: require.resolve("./src/css/custom.css"), customCss: require.resolve("./src/css/custom.css"),
@ -73,7 +73,7 @@ const config = {
title: "Squiggle", title: "Squiggle",
logo: { logo: {
alt: "Squiggle Logo", alt: "Squiggle Logo",
src: "img/logo.svg", src: "img/quri-logo.png",
}, },
items: [ items: [
{ {
@ -85,7 +85,7 @@ const config = {
{ to: "/blog", label: "Blog", position: "left" }, { to: "/blog", label: "Blog", position: "left" },
{ to: "/playground", label: "Playground", position: "left" }, { to: "/playground", label: "Playground", position: "left" },
{ {
href: "https://github.com/QURIresearch/squiggle", href: "https://github.com/quantified-uncertainty/squiggle",
label: "GitHub", label: "GitHub",
position: "right", position: "right",
}, },
@ -103,7 +103,7 @@ const config = {
}, },
{ {
label: "GitHub", label: "GitHub",
href: "https://github.com/QURIresearch/squiggle", href: "https://github.com/quantified-uncertainty/squiggle",
}, },
], ],
}, },

View File

@ -22,10 +22,7 @@ function HomepageHeader() {
export default function Home() { export default function Home() {
const { siteConfig } = useDocusaurusContext(); const { siteConfig } = useDocusaurusContext();
return ( return (
<Layout <Layout title={`${siteConfig.title}`} description="An estimation language">
title={`Hello from ${siteConfig.title}`}
description="Description will go into a meta tag in <head />"
>
<HomepageHeader /> <HomepageHeader />
<main> <main>
<HomepageFeatures /> <HomepageFeatures />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB