text:
### A Pluto.jl notebook ###
# v0.16.0

using Markdown
using InteractiveUtils

# ╔═╡ bf54eece-fc02-11ea-3dbc-b37a5644eab1
using Plots

# ╔═╡ cd9cc940-fc02-11ea-2a40-19bc6f79a6d3
using LaTeXStrings

# ╔═╡ dad114fe-fbfb-11ea-32dd-a302838af30f
md"# Linear Programming: Introduction"

# ╔═╡ fdab0c70-fbfb-11ea-116d-9f1b613f9d0d
md"""## Definition

Formally, a linear program is an optimization problem of the form:

```math
\begin{aligned}
\min \vec{c}^\mathsf{T}\vec x&\\
\textrm{ subject to }&\begin{cases}
\mathbf{A}\vec x=\vec b\\
\vec x\ge\vec 0
\end{cases}
\end{aligned}
```

where $\vec c\in\mathbb R^n$, $\vec b\in\mathbb R^m$ and $\mathbf A \in \mathbb R^{m\times n}$. The vector inequality $\vec x\ge\vec 0$ means that each component of $\vec x$ is nonnegative. Several variations of this problem are possible; eg. instead of minimizing, we can maximize, or the constraints may be in the form of inequalities, such as $\mathbf A\vec x\ge \vec b$ or $\mathbf A\vec x\le\vec b$. We shall see later, these variations can all be rewritten into the standard form."""

# ╔═╡ 0d88a212-fbfc-11ea-37ae-c5e0c6a894e8
md"""## Example

A manufacturer produces  four different  products  $X_1$, $X_2$, $X_3$ and $X_4$. There are three inputs to this production process:

- labor in man weeks,
- kilograms of raw material A, and
- boxes  of raw  material  B.

Each product has different input requirements. In determining each  week's production schedule, the manufacturer cannot use more than the available amounts of  manpower and the two raw  materials:

|Inputs|$X_1$|$X_2$|$X_3$|$X_4$|Availabilities|
|------|-----|-----|-----|-----|--------------|
|Person-weeks|1|2|1|2|20|
|Kilograms of material A|6|5|3|2|100|
|Boxes of material B|3|4|9|12|75|
|Production level|$x_1$|$x_2$|$x_3$|$x_4$| |

These constraints can be written in mathematical form

```math
\begin{aligned}
x_1+2x_2+x_3+2x_4\le&20\\
6x_1+5x_2+3x_3+2x_4\le&100\\
3x_1+4x_2+9x_3+12x_4\le&75
\end{aligned}
```

Because negative production levels are not meaningful, we must impose the following nonnegativity constraints on the production levels:

```math
x_i\ge0,\qquad i=1,2,3,4
```

Now suppose that one unit of product $X_1$ sells for €6 and $X_2$, $X_3$ and $X_4$ sell for €4, €7 and €5, respectively. Then, the total revenue for any production decision $\left(x_1,x_2,x_3,x_4\right)$ is

```math
f\left(x_1,x_2,x_3,x_4\right)=6x_1+4x_2+7x_3+5x_4
```

The problem is then to maximize $f$ subject to the given constraints."""

# ╔═╡ 67071830-fbfc-11ea-3925-798d3d288500
md"""## Vector Notation

Using vector notation with

```math
\vec x = \begin{pmatrix}
x_1\\x_2\\x_3\\x_4
\end{pmatrix}
```

the problem can be written in the compact form

```math
\max
\begin{pmatrix}6&4&7&5\end{pmatrix}
\begin{pmatrix}
x_1\\x_2\\x_3\\x_4
\end{pmatrix}\\
\textrm{ subject to }
\begin{cases}
\begin{pmatrix}
1&2&1&2\\
6&5&3&2\\
3&4&9&12
\end{pmatrix}
\begin{pmatrix}
x_1\\x_2\\x_3\\x_4
\end{pmatrix}\le
\begin{pmatrix}
20\\100\\75
\end{pmatrix}\\
\begin{pmatrix}
x_1\\x_2\\x_3\\x_4
\end{pmatrix}\ge
\begin{pmatrix}
0\\0\\0\\0
\end{pmatrix}
\end{cases}
```
 """

# ╔═╡ 3bb281f0-fc02-11ea-34f0-fd00648c27bb
md"""## Two-dimensional Linear Program

Many fundamental concepts of linear programming are easily illustrated in two-dimensional space.

Consider the following linear program:

```math
\begin{aligned}
\max&
\begin{pmatrix}
1&5
\end{pmatrix}
\begin{pmatrix}
x_1\\
x_2
\end{pmatrix}&\\
\textrm{ subject to }
&\begin{cases}
\begin{pmatrix}
5&6\\
3&2
\end{pmatrix}
\begin{pmatrix}
x_1\\
x_2
\end{pmatrix}\le
\begin{pmatrix}
30\\
12
\end{pmatrix}\\
\begin{pmatrix}
x_1\\
x_2
\end{pmatrix}\ge
\begin{pmatrix}
0\\
0
\end{pmatrix}
\end{cases}
\end{aligned}
```
"""

# ╔═╡ e5488250-fc02-11ea-0bc1-4365461fb202
let
	x = -2:6
	plot(x, (30 .- 5 .* x) ./ 6, linestyle=:dash, label=L"5x_1+6x_2=30")
	plot!(x, (12 .- 3 .* x) ./ 2, linestyle=:dash, label=L"3x_1+2x_2=12")
	plot!([0,4,1.5,0,0],[0,0,3.75,5,0], linewidth=2, label="constraints")
	plot!(x, -x ./ 5, label=L"f\left(x_1,x_2\right)=x_1+5x_2=0")
	plot!(x, (25 .- x) ./ 5, label=L"f\left(x_1,x_2\right)=x_1+5x_2=25")
end

# ╔═╡ 08de4fb0-fc03-11ea-08fb-616f792f7c7f
md"""## Slack Variables

Theorems and solution techniques are usually stated for problems in standard form. other forms of linear programs can be converted as the standard form. If a linear program is in the form

```math
\begin{aligned}
\min &\vec{c}^\mathsf{T}\vec x\\
\textrm{ subject to }& \begin{cases}
\mathbf{A}\vec x\ge \vec b\\
\vec x\ge\vec 0
\end{cases}
\end{aligned}
```

then by introducing _surplus variables_, we can convert the orginal problem into the standard form

```math
\begin{aligned}
\min& \vec{c}^\mathsf{T}\vec x\\
\textrm{ subject to }& \begin{cases}
\mathbf{A}\vec x-\mathbf I\vec y = \vec b\\
\vec x\ge\vec 0\\
\vec y\ge\vec 0
\end{cases}
\end{aligned}
```

where $\mathbf I$ is the $m\times m$ identity matrix.

If, on the other hand, the constraints have the form

```math
\begin{cases}
\mathbf{A}\vec x\le b\\
\vec x\ge\vec 0
\end{cases}
```

then we introduce the _slack variables_ to convert the constraints into the form

```math
\begin{cases}
\mathbf{A}\vec x+\mathbf I\vec y = \vec b\\
\vec x\ge\vec 0\\
\vec y\ge\vec 0
\end{cases}
```

Consider the following optimization problem

```math
\begin{aligned}
\max& x_2-x_1\\
\textrm{ subject to }&
\begin{cases}
3x_1=x_2-5\\
\left|x_2\right|\le2\\
x_1\le0
\end{cases}
\end{aligned}
```

To convert the problem into a standard form, we perform the following steps:

1. Change the objective function to:

```math
\min x_1 - x_2
```

2. Substitute $x_1=-x_1^\prime$.

3. Write $\left|x_2\right|\le2$ as $x_2\le 2$ and $-x_2\le 2$.

4. Introduce slack variables $y_1$ and $y_2$, and convert the inequalities above to

```math
\begin{cases}
\hphantom{-}x_2 + y_1 =2\\
-x_2+y_2 =2
\end{cases}
```

5. Write $x_2=u-v$ with $u,v\ge0$.

Hence, we obtain

```math
\begin{aligned}
\min& -x_1^\prime-u+v\\
\textrm{ subject to }&
\begin{cases}
3x_1^\prime+u-v=5\\
u-v+y_1=2\\
v-u+y_2=2\\
x_1^\prime,u,v,y_1,y_2\ge0
\end{cases}
\end{aligned}
```
"""

# ╔═╡ cfd86bf0-fc03-11ea-22ef-b99d3e3fbfce
md"""## Fundamental Theorem of Linear Programming

We consider the system of equalities

```math
\mathbf{A}\vec x=\vec b
```

where $\mathrm{rank}\,\mathbf A=m$.

Let $\mathbf B$ a square matrix whose columns are $m$ linearly independent columns of $\mathbf A$. If necessary, we reorder the columns of $\mathbf A$ so that the columns in $\mathbf B$ appear first: $\mathbf A$ has the form $\left(\mathbf B |\mathbf N\right)$.

The matrix is nonsingular, and thus we can solve the equation

```math
\mathbf B\vec x_\mathbf B = \vec b
```

The solution is $\vec x_\mathbf B = \mathbf B^{-1}\vec b$.

Let $\vec x$ be the vector whose first $m$ components are equal to $\vec x_\mathbf B$ and the remaining components are equal to zero. Then $\vec x$ is a solution to $\mathbf A\vec x=\vec b$. We call $\vec x$  a _basic solution_. Its components refering to the the components of $\vec x_\mathbf B$ are called _basic variables_.

- If some of the basic variables are zero, then the basic solution is _degenerate_.
- A vector $\vec x$ satisfying $\mathbf A\vec x=\vec b$, $\vec x \ge \vec 0$, is said to be a _feasible solution_.
- A feasible solution that is also basic is called a _basic feasible solution_.

The fundamental theorem of linear programming states that when solving a linear programming problem, we need only consider basic feasible solutions. This is because the optimal value (if it exists) is always achieved at a basic solution."""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

[compat]
LaTeXStrings = "~1.2.1"
Plots = "~1.22.1"
"""

# ╔═╡ 00000000-0000-0000-0000-000000000002
PLUTO_MANIFEST_TOML_CONTENTS = """
# This file is machine-generated - editing it directly is not advised

[[Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "84918055d15b3114ede17ac6a7182f68870c16f7"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.1"

[[ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[Bzip2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2"
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
version = "1.0.8+0"

[[Cairo_jll]]
deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "f2202b55d816427cd385a9a4f3ffb226bee80f99"
uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a"
version = "1.16.1+0"

[[ColorSchemes]]
deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random"]
git-tree-sha1 = "9995eb3977fbf67b86d0a0a0508e83017ded03f2"
uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
version = "3.14.0"

[[ColorTypes]]
deps = ["FixedPointNumbers", "Random"]
git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597"
uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
version = "0.11.0"

[[Colors]]
deps = ["ColorTypes", "FixedPointNumbers", "Reexport"]
git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40"
uuid = "5ae59095-9a9b-59fe-a467-6f913c188581"
version = "0.12.8"

[[Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "4866e381721b30fac8dda4c8cb1d9db45c8d2994"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.37.0"

[[CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[Contour]]
deps = ["StaticArrays"]
git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7"
uuid = "d38c429a-6771-53c6-b99e-75d170b6e991"
version = "0.5.7"

[[DataAPI]]
git-tree-sha1 = "bec2532f8adb82005476c141ec23e921fc20971b"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.8.0"

[[DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "7d9d316f04214f7efdbb6398d545446e246eff02"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.10"

[[DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[DelimitedFiles]]
deps = ["Mmap"]
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"

[[Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"

[[Downloads]]
deps = ["ArgTools", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[EarCut_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "3f3a2501fa7236e9b911e0f7a588c657e822bb6d"
uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5"
version = "2.2.3+0"

[[Expat_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b3bfd02e98aedfa5cf885665493c5598c350cd2f"
uuid = "2e619515-83b5-522b-bb60-26c02a35a201"
version = "2.2.10+0"

[[FFMPEG]]
deps = ["FFMPEG_jll"]
git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8"
uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a"
version = "0.4.1"

[[FFMPEG_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"]
git-tree-sha1 = "d8a578692e3077ac998b50c0217dfd67f21d1e5f"
uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5"
version = "4.4.0+0"

[[FixedPointNumbers]]
deps = ["Statistics"]
git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc"
uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
version = "0.8.4"

[[Fontconfig_jll]]
deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "21efd19106a55620a188615da6d3d06cd7f6ee03"
uuid = "a3f928ae-7b40-5064-980b-68af3947d34b"
version = "2.13.93+0"

[[Formatting]]
deps = ["Printf"]
git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8"
uuid = "59287772-0a20-5a39-b81b-1366585eb4c0"
version = "0.4.2"

[[FreeType2_jll]]
deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9"
uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7"
version = "2.10.4+0"

[[FriBidi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91"
uuid = "559328eb-81f9-559d-9380-de523a88c83c"
version = "1.0.10+0"

[[GLFW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"]
git-tree-sha1 = "dba1e8614e98949abfa60480b13653813d8f0157"
uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89"
version = "3.3.5+0"

[[GR]]
deps = ["Base64", "DelimitedFiles", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Printf", "Random", "Serialization", "Sockets", "Test", "UUIDs"]
git-tree-sha1 = "c2178cfbc0a5a552e16d097fae508f2024de61a3"
uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71"
version = "0.59.0"

[[GR_jll]]
deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "ef49a187604f865f4708c90e3f431890724e9012"
uuid = "d2c73de3-f751-5644-a686-071e5b155ba9"
version = "0.59.0+0"

[[GeometryBasics]]
deps = ["EarCut_jll", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"]
git-tree-sha1 = "58bcdf5ebc057b085e58d95c138725628dd7453c"
uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
version = "0.4.1"

[[Gettext_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046"
uuid = "78b55507-aeef-58d4-861c-77aaff3498b1"
version = "0.21.0+0"

[[Glib_jll]]
deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "7bf67e9a481712b3dbe9cb3dac852dc4b1162e02"
uuid = "7746bdde-850d-59dc-9ae8-88ece973131d"
version = "2.68.3+0"

[[Graphite2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011"
uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472"
version = "1.3.14+0"

[[Grisu]]
git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2"
uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe"
version = "1.0.2"

[[HTTP]]
deps = ["Base64", "Dates", "IniFile", "Logging", "MbedTLS", "NetworkOptions", "Sockets", "URIs"]
git-tree-sha1 = "60ed5f1643927479f845b0135bb369b031b541fa"
uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3"
version = "0.9.14"

[[HarfBuzz_jll]]
deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"]
git-tree-sha1 = "8a954fed8ac097d5be04921d595f741115c1b2ad"
uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566"
version = "2.8.1+0"

[[IniFile]]
deps = ["Test"]
git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8"
uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f"
version = "0.5.0"

[[InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[IterTools]]
git-tree-sha1 = "05110a2ab1fc5f932622ffea2a003221f4782c18"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.3.0"

[[IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.3.0"

[[JSON]]
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
git-tree-sha1 = "8076680b162ada2a031f707ac7b4953e30667a37"
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
version = "0.21.2"

[[JpegTurbo_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d735490ac75c5cb9f1b00d8b5509c11984dc6943"
uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8"
version = "2.1.0+0"

[[LAME_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c"
uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d"
version = "3.100.1+0"

[[LZO_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6"
uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac"
version = "2.10.1+0"

[[LaTeXStrings]]
git-tree-sha1 = "c7f1c695e06c01b95a67f0cd1d34994f3e7db104"
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
version = "1.2.1"

[[Latexify]]
deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "Printf", "Requires"]
git-tree-sha1 = "a4b12a1bd2ebade87891ab7e36fdbce582301a92"
uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
version = "0.15.6"

[[LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[Libffi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "761a393aeccd6aa92ec3515e428c26bf99575b3b"
uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490"
version = "3.2.2+0"

[[Libgcrypt_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"]
git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae"
uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4"
version = "1.8.7+0"

[[Libglvnd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"]
git-tree-sha1 = "7739f837d6447403596a75d19ed01fd08d6f56bf"
uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29"
version = "1.3.0+3"

[[Libgpg_error_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9"
uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8"
version = "1.42.0+0"

[[Libiconv_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "42b62845d70a619f063a7da093d995ec8e15e778"
uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531"
version = "1.16.1+1"

[[Libmount_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73"
uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9"
version = "2.35.0+0"

[[Libtiff_jll]]
deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"]
git-tree-sha1 = "340e257aada13f95f98ee352d316c3bed37c8ab9"
uuid = "89763e89-9b03-5906-acba-b20f662cd828"
version = "4.3.0+0"

[[Libuuid_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066"
uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700"
version = "2.36.0+0"

[[LinearAlgebra]]
deps = ["Libdl"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

[[MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "5a5bc6bf062f0f95e62d0fe0a2d99699fed82dd9"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.8"

[[Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"

[[MbedTLS]]
deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"]
git-tree-sha1 = "1c38e51c3d08ef2278062ebceade0e46cefc96fe"
uuid = "739be429-bea8-5141-9913-cc70e7f3736d"
version = "1.0.3"

[[MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"

[[Measures]]
git-tree-sha1 = "e498ddeee6f9fdb4551ce855a46f54dbd900245f"
uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
version = "0.3.1"

[[Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "bf210ce90b6c9eed32d25dbcae1ebc565df2687f"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.0.2"

[[Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"

[[MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[NaNMath]]
git-tree-sha1 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.5"

[[NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[Ogg_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "7937eda4681660b4d6aeeecc2f7e1c81c8ee4e2f"
uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051"
version = "1.3.5+0"

[[OpenSSL_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "15003dcb7d8db3c6c857fda14891a539a8f2705a"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "1.1.10+0"

[[Opus_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720"
uuid = "91d4177d-7536-5919-b921-800302f37372"
version = "1.3.2+0"

[[OrderedCollections]]
git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.4.1"

[[PCRE_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b2a7af664e098055a7529ad1a900ded962bca488"
uuid = "2f80f16e-611a-54ab-bc61-aa92de5b98fc"
version = "8.44.0+0"

[[Parsers]]
deps = ["Dates"]
git-tree-sha1 = "438d35d2d95ae2c5e8780b330592b6de8494e779"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.0.3"

[[Pixman_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29"
uuid = "30392449-352a-5448-841d-b1acce4e97dc"
version = "0.40.1+0"

[[Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[PlotThemes]]
deps = ["PlotUtils", "Requires", "Statistics"]
git-tree-sha1 = "a3a964ce9dc7898193536002a6dd892b1b5a6f1d"
uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
version = "2.0.1"

[[PlotUtils]]
deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"]
git-tree-sha1 = "2537ed3c0ed5e03896927187f5f2ee6a4ab342db"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.0.14"

[[Plots]]
deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs"]
git-tree-sha1 = "4c2637482176b1c2fb99af4d83cb2ff0328fc33c"
uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
version = "1.22.1"

[[Preferences]]
deps = ["TOML"]
git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.2"

[[Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[Qt5Base_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"]
git-tree-sha1 = "ad368663a5e20dbb8d6dc2fddeefe4dae0781ae8"
uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1"
version = "5.15.3+0"

[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[Random]]
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[RecipesBase]]
git-tree-sha1 = "44a75aa7a527910ee3d1751d1f0e4148698add9e"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.1.2"

[[RecipesPipeline]]
deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"]
git-tree-sha1 = "7ad0dfa8d03b7bcf8c597f59f5292801730c55b8"
uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c"
version = "0.4.1"

[[Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "4036a3bd08ac7e968e27c203d45f5fff15020621"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.1.3"

[[SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"

[[Scratch]]
deps = ["Dates"]
git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.1.0"

[[Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"

[[SharedArrays]]
deps = ["Distributed", "Mmap", "Random", "Serialization"]
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"

[[Showoff]]
deps = ["Dates", "Grisu"]
git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de"
uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f"
version = "1.0.3"

[[Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"

[[SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.0.1"

[[SparseArrays]]
deps = ["LinearAlgebra", "Random"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[[StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "3240808c6d463ac46f1c1cd7638375cd22abbccb"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.2.12"

[[Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"

[[StatsAPI]]
git-tree-sha1 = "1958272568dc176a1d881acb797beb909c785510"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.0.0"

[[StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "8cbbc098554648c84f79a463c9ff0fd277144b6c"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.33.10"

[[StructArrays]]
deps = ["Adapt", "DataAPI", "StaticArrays", "Tables"]
git-tree-sha1 = "2ce41e0d042c60ecd131e9fb7154a3bfadbf50d3"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.3"

[[TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
git-tree-sha1 = "1162ce4a6c4b7e31e0e6b14486a6986951c73be9"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.5.2"

[[Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[[URIs]]
git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355"
uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
version = "1.3.0"

[[UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[[Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[[Wayland_jll]]
deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"]
git-tree-sha1 = "3e61f0b86f90dacb0bc0e73a0c5a83f6a8636e23"
uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89"
version = "1.19.0+0"

[[Wayland_protocols_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll"]
git-tree-sha1 = "2839f1c1296940218e35df0bbb220f2a79686670"
uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91"
version = "1.18.0+4"

[[XML2_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"]
git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a"
uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a"
version = "2.9.12+0"

[[XSLT_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"]
git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a"
uuid = "aed1982a-8fda-507f-9586-7b0439959a61"
version = "1.1.34+0"

[[Xorg_libX11_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"]
git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527"
uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc"
version = "1.6.9+4"

[[Xorg_libXau_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e"
uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec"
version = "1.0.9+4"

[[Xorg_libXcursor_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd"
uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724"
version = "1.2.0+4"

[[Xorg_libXdmcp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4"
uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05"
version = "1.1.3+4"

[[Xorg_libXext_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3"
uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3"
version = "1.3.4+4"

[[Xorg_libXfixes_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4"
uuid = "d091e8ba-531a-589c-9de9-94069b037ed8"
version = "5.0.3+4"

[[Xorg_libXi_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"]
git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246"
uuid = "a51aa0fd-4e3c-5386-b890-e753decda492"
version = "1.7.10+4"

[[Xorg_libXinerama_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"]
git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123"
uuid = "d1454406-59df-5ea1-beac-c340f2130bc3"
version = "1.1.4+4"

[[Xorg_libXrandr_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"]
git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631"
uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484"
version = "1.5.2+4"

[[Xorg_libXrender_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96"
uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa"
version = "0.9.10+4"

[[Xorg_libpthread_stubs_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb"
uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74"
version = "0.1.0+3"

[[Xorg_libxcb_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"]
git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6"
uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b"
version = "1.13.0+3"

[[Xorg_libxkbfile_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"]
git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2"
uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a"
version = "1.1.0+4"

[[Xorg_xcb_util_image_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97"
uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b"
version = "0.4.0+1"

[[Xorg_xcb_util_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"]
git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1"
uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5"
version = "0.4.0+1"

[[Xorg_xcb_util_keysyms_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00"
uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7"
version = "0.4.0+1"

[[Xorg_xcb_util_renderutil_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e"
uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e"
version = "0.3.9+1"

[[Xorg_xcb_util_wm_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"]
git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67"
uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361"
version = "0.4.1+1"

[[Xorg_xkbcomp_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"]
git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b"
uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4"
version = "1.4.2+4"

[[Xorg_xkeyboard_config_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"]
git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d"
uuid = "33bec58e-1273-512f-9401-5d533626f822"
version = "2.27.0+4"

[[Xorg_xtrans_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845"
uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10"
version = "1.4.0+3"

[[Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[Zstd_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "cc4bf3fdde8b7e3e9fa0351bdeedba1cf3b7f6e6"
uuid = "3161d3a3-bdf6-5164-811a-617609db77b4"
version = "1.5.0+0"

[[libass_jll]]
deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "5982a94fcba20f02f42ace44b9894ee2b140fe47"
uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0"
version = "0.15.1+0"

[[libfdk_aac_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "daacc84a041563f965be61859a36e17c4e4fcd55"
uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280"
version = "2.0.2+0"

[[libpng_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c"
uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f"
version = "1.6.38+0"

[[libvorbis_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"]
git-tree-sha1 = "c45f4e40e7aafe9d086379e5578947ec8b95a8fb"
uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a"
version = "1.3.7+0"

[[nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"

[[x264_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "4fea590b89e6ec504593146bf8b988b2c00922b2"
uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a"
version = "2021.5.5+0"

[[x265_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9"
uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76"
version = "3.5.0+0"

[[xkbcommon_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"]
git-tree-sha1 = "ece2350174195bb31de1a63bea3a41ae1aa593b6"
uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd"
version = "0.9.1+5"
"""

# ╔═╡ Cell order:
# ╟─dad114fe-fbfb-11ea-32dd-a302838af30f
# ╟─fdab0c70-fbfb-11ea-116d-9f1b613f9d0d
# ╟─0d88a212-fbfc-11ea-37ae-c5e0c6a894e8
# ╟─67071830-fbfc-11ea-3925-798d3d288500
# ╟─3bb281f0-fc02-11ea-34f0-fd00648c27bb
# ╠═bf54eece-fc02-11ea-3dbc-b37a5644eab1
# ╠═cd9cc940-fc02-11ea-2a40-19bc6f79a6d3
# ╠═e5488250-fc02-11ea-0bc1-4365461fb202
# ╟─08de4fb0-fc03-11ea-08fb-616f792f7c7f
# ╟─cfd86bf0-fc03-11ea-22ef-b99d3e3fbfce
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
using Documenter
using NestedSamplers

DocMeta.setdocmeta!(
    NestedSamplers,
    :DocTestSetup,
    :(using NestedSamplers);
    recursive=true
)

makedocs(
    sitename = "NestedSamplers.jl",
    pages = [
        "Home" => "index.md",
        "Examples" => [
            "Gaussian Shells" => "examples/shells.md",
            "Correlated Gaussian" => "examples/correlated.md",
            "Eggbox" => "examples/eggbox.md",
        ],
        "Benchmarks" => "benchmarks.md",
        "API/Reference" => "api.md"
    ],
    format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"),
    modules = [NestedSamplers],
    # https://github.com/JuliaLang/julia/pull/37085#issuecomment-683356098
    doctestfilters = [
        r"{([a-zA-Z0-9]+,\s?)+[a-zA-Z0-9]+}",
        r"(Array{[a-zA-Z0-9]+,\s?1}|Vector{[a-zA-Z0-9]+})",
        r"(Array{[a-zA-Z0-9]+,\s?2}|Matrix{[a-zA-Z0-9]+})",
    ]
)

deploydocs(repo = "github.com/TuringLang/NestedSamplers.jl.git", push_preview=true, devbranch="main")

ext: jl


text:
"""
    rand_categorical(x::Vector{<:Real})

Pick one index in `1:length(x)` at random using the elements of `x` as weights.
"""
function rand_categorical(x::Vector{<:Real}, s = sum(x))
    if isempty(x)
        return 0
    end
    r = rand()
    i = 1
    t = x[i]
    while r*s > t
        i += 1
        t += x[i]
    end
    return i
end

"""
    rand_combination(n,k)

Return a random combination of `k` elements in `1:n`.
"""
function rand_combination(n::Integer, k::Integer)
    if k < n && k > 0
        c = Vector{Int64}(undef, k)
        s = BitSet(1:n)
        for i in 1:k
            c[i] = rand(s)
            delete!(s, c[i])
        end
        return c
    else
        return []
    end
end


text:
# tetrhedron.jl

using GeometryTypes
using StaticArrays

struct Tetrahedron
    vertices::SVector{4,Int}
    neighbors::MVector{4,Int}
end

function permute(tet::Tetrahedron, evenorodd::Int)::Tetrahedron
    if (evenorodd % 2) == 0
        Tetrahedron([tet.vertices[2],tet.vertices[1],tet.vertices[4],tet.vertices[3]],
                          [tet.neighbors[2],tet.neighbors[1],tet.neighbors[4],tet.neighbors[3]])
    else
        Tetrahedron([tet.vertices[4],tet.vertices[3],tet.vertices[2],tet.vertices[1]],
                          [tet.neighbors[4],tet.neighbors[3],tet.neighbors[2],tet.neighbors[1]])
    end
end

function rotate(tet::Tetrahedron, pivot::Int)::Tetrahedron
    if pivot == 1
        Tetrahedron([tet.vertices[1], tet.vertices[4], tet.vertices[2], tet.vertices[3]],
                  [tet.neighbors[1],tet.neighbors[4],tet.neighbors[2],tet.neighbors[3]])
    elseif pivot == 2
        Tetrahedron([tet.vertices[4], tet.vertices[2], tet.vertices[1], tet.vertices[3]],
                  [tet.neighbors[4],tet.neighbors[2],tet.neighbors[1],tet.neighbors[3]])
    elseif pivot == 3
        Tetrahedron([tet.vertices[4], tet.vertices[1], tet.vertices[3], tet.vertices[2]],
                  [tet.neighbors[4],tet.neighbors[1],tet.neighbors[3],tet.neighbors[2]])
    elseif pivot == 4
        Tetrahedron([tet.vertices[3], tet.vertices[1], tet.vertices[2], tet.vertices[4]],
                  [tet.neighbors[3],tet.neighbors[1],tet.neighbors[2],tet.neighbors[4]])
    else
        tet
    end
end

function getface(tet::Tetrahedron, index::Int)::Face{3,Int}
    face::Array{Int,1} = tet.vertices[setdiff(1:4,index)]
    if index % 2 == 1
        Face{3,Int}(face[1],face[3],face[2])
    else
        Face{3,Int}(face...)
    end
end


text:
module wd

end

max_stars_repo_name: tmaone/xsh

max_issues_repo_name: turing-complete/xsh

max_forks_repo_name: turing-complete/xsh


text:
module AlarmReport
    include( "LogLstLib.jl")

    using Printf
    using ...SegParaAlarmProc
    function LogAlarm(alrmobj,isNew::Bool=false)
        chnid , fl,DTStr = SegParaAlarmProc.get防区编号和FL(alrmobj.SC ,  alrmobj.t0 )
        a= @sprintf( "%s,%04u,%04u,%05u,%014u,%014u,%014u,%01u,%06u,%s\r\n",alrmobj.AlarmID,
        alrmobj.S1 ,
        alrmobj.S2,
        alrmobj.SC ,
        alrmobj.t0 ,
        alrmobj.tfresh,
        alrmobj.Tc,
        chnid,
        fl    ,
        DTStr
        )
        # @info "----SegParaAlarmProc.CalChn1_2Obj.CfgInfoObj.meterperSeg-- ???:",SegParaAlarmProc.CalChn1_2Obj.CfgInfoObj.meterperSeg
        if isNew == true
            # a[1]=
            LogEvent( "N"*a[2:end] )
        else
            LogEvent( a  )
        end

    end
end

max_stars_repo_name: wangzhongtian/fiberAlarmAnalyseTool

max_issues_repo_name: wangzhongtian/fiberAlarmAnalyseTool

max_forks_repo_name: wangzhongtian/fiberAlarmAnalyseTool


text:
module Test

using Test, GridArrays, DomainSets

using GridArrays: hasextension, extend, rescale

function test_interval_grid(grid::AbstractGrid, show_timings=false)
    test_generic_grid(grid, show_timings=show_timings)
    T = eltype(grid)
    g1 = rescale(rescale(grid, -T(10), T(3)), infimum(covering(grid)), supremum(covering(grid)))
    @test covering(g1) ≈ covering(grid)
    g2 = resize(grid, length(grid)<<1)
    @test length(g2) == length(grid)<<1

    g3 = resize(g1, length(grid)<<1)
    @test length(g3) == length(grid)<<1

    g4 = rescale(rescale(g2, -T(10), T(3)), infimum(covering(g2)), supremum(covering(g2)))
    @test covering(g4) ≈ covering(g2)

    if hasextension(grid)
        @test extend(grid,3) isa typeof(grid)
    end
    if grid isa AbstractEquispacedGrid
        @test step(grid) ≈ grid[2]-grid[1]
    end
end

function test_generic_grid(grid; show_timings=false)
    io = IOBuffer()
    show(io, grid)
    @test length(take!(io))>0
    L = length(grid)
    @test ndims(grid) == length(grid[1])

    T = eltype(grid)
    FT = prectype(T)

    grid_iterator(grid)

    # Test two types of iterations over a grid.
    # Make sure there are L elements. Do some computation on each point,
    # and make sure the results are the same.
    (l1,sum1) = grid_iterator1(grid)
    @test l1 == L
    (l2,sum2) = grid_iterator2(grid)
    @test l2 == L
    @test sum1 ≈ sum2

    if typeof(grid) <: AbstractGrid1d
        # Make sure that 1d grids return points, not vectors with one point.
        @test eltype(grid) <: Number
    end

    if hasextension(grid)
        g_ext = extend(grid, 2)
        @test grid ≈ g_ext[1:2:end]
        # for i in 1:length(grid)
        #     @test grid[i] ≈ g_ext[2i-1]
        # end
    end

    if show_timings
        t = @timed grid_iterator1(grid)
        t = @timed grid_iterator1(grid)
        print_with_color(:blue, "Eachindex: ")
        println(t[3], " bytes in ", t[2], " seconds")
        t = @timed grid_iterator2(grid)
        print_with_color(:blue, "Each x in grid: ")
        println(t[3], " bytes in ", t[2], " seconds")
    end
end

function grid_iterator(grid)
    grid_iteration_equal = true
    for (i,j) in zip(1:length(grid), eachindex(grid))
        grid_iteration_equal &= grid[i] == grid[j]
    end
    @test grid_iteration_equal
end

function grid_iterator1(grid)
    l = 0
    s = zero(prectype(grid))
    for i in eachindex(grid)
        x = grid[i]
        l += 1
        s += sum(x)
    end
    (l,s)
end

function grid_iterator2(grid)
    l = 0
    s = zero(prectype(grid))
    for x in grid
        l += 1
        s += sum(x)
    end
    (l,s)
end

end


text:
# Multiple variables alone a line across multiple frames.
#
# Hongyang Zhou, hyzhou@umich.edu

using Vlasiator, PyPlot, Glob, Printf

files = glob("bulk*.vlsv", ".")
nfiles = length(files)

Re = Vlasiator.Re # Earth radii
x1, x2 = 8.0, 29.0
point1 = [x1, 0, 0] .* Re
point2 = [x2, 0, 0] .* Re

meta = load(files[1])
cellids, distances, coords = getcellinline(meta, point1, point2)

loc = range(x1, x2, length=length(cellids))

close(meta.fid)

ρmin, ρmax = 0.0, 10.0     # [amu/cc]
vmin, vmax = -640.0, 0.0   # [km/s]
pmin, pmax = 0.0, 1.82     # [nPa]
bmin, bmax = -25.0, 60.0   # [nT]

fontsize = 14

fig, axs = plt.subplots(4, 1, figsize=(10, 15), sharex=true, constrained_layout=true)

axs[end].set_xlim(x1, x2)

axs[1].set_ylim(ρmin, ρmax)
axs[2].set_ylim(vmin, vmax)
axs[3].set_ylim(pmin, pmax)
axs[4].set_ylim(bmin, bmax)
for ax in axs
   ax.xaxis.set_minor_locator(matplotlib.ticker.AutoMinorLocator())
   ax.yaxis.set_minor_locator(matplotlib.ticker.AutoMinorLocator())
   ax.grid(true)
end

axs[end].set_xlabel("x [Re]"; fontsize)
axs[1].set_ylabel("Density [amu/cc]"; fontsize)
axs[2].set_ylabel("Velocity [km/s]"; fontsize)
axs[3].set_ylabel("Pressure [nPa]"; fontsize)
axs[4].set_ylabel("Magnetic field [nT]"; fontsize)

# Loop over snapshots
for (i, file) in enumerate(files)
   isfile("out/"*file[end-8:end-5]*".png") && continue

   println("i = $i/$nfiles, file = $file")
   local meta = load(file)

   p_extract = readvariable(meta, "vg_pressure", cellids) .* 1e9 |> vec # [nPa]
   rho_extract = readvariable(meta, "proton/vg_rho", cellids) |> vec
   v_extract = readvariable(meta, "proton/vg_v", cellids)
   vmag2_extract = sum(v_extract.^2, dims=1) |> vec
   pdyn_extract = rho_extract .* Vlasiator.mᵢ .* vmag2_extract .* 1e9 # [nPa]

   bz = readvariable(meta, "vg_b_vol", cellids)[3,:] .* 1e9 #[nT]

   imagnetopause_ = findfirst(<(0.0), bz)

   axs[1].plot(loc, rho_extract ./ 1e6, label="Proton density", color="#1f77b4")
   vl1 = axs[1].vlines(loc[imagnetopause_], ρmin, ρmax;
      colors="r", linestyle="dashed", alpha=0.5)

   axs[2].plot(loc, v_extract[1,:] ./ 1e3, label="Vx", color="#1f77b4")
   vl2 = axs[2].vlines(loc[imagnetopause_], vmin, vmax;
      colors="r", linestyle="dashed", alpha=0.5)

   axs[3].plot(loc, pdyn_extract, label="Dynamic", color="#1f77b4")
   axs[3].plot(loc, p_extract, label="Thermal", color="#ff7f0e")
   vl3 = axs[3].vlines(loc[imagnetopause_], pmin, pmax;
      colors="r", linestyle="dashed", alpha=0.5)

   axs[4].plot(loc, bz, label="Bz", color="#1f77b4")
   hl4 = axs[4].hlines(0.0, loc[1], loc[end], colors="k", linestyle="dashed", alpha=0.2)
   vl4 = axs[4].vlines(loc[imagnetopause_], bmin, bmax;
       colors="r", linestyle="dashed", alpha=0.5)

   str_title = @sprintf "t= %4.1fs" meta.time
   axs[1].set_title(str_title; fontsize)

   axs[2].legend(;loc="upper right", fontsize)
   axs[3].legend(;loc="upper left",  fontsize)
   axs[4].legend(;loc="upper right", fontsize)

   savefig("out/"*file[end-8:end-5]*".png", bbox_inches="tight")

   for ax in axs
      for line in ax.get_lines()
         line.remove()
      end
   end
   for line in (vl1, vl2, vl3, vl4, hl4)
      line.remove()
   end
end

close(fig)
println("Finished!")


text:
import Base: *, sort
using Random, Statistics, DataFrames, CSV
using BioSequences, FASTX, XLSX, CPUTime

#########
#The following functions are the base set of tools that this program uses

# Overload the concatenation operator to combine a sequence and
# a single base, i.e. dna"AGCGTGC" * DNA_T
function *(seq::LongDNASeq, base::DNA)
    seq * LongDNASeq([base])
end

# Overload sort to order DNA codes by degeneracy:
#   A,G,C,T,M,R,W,S,Y,K,V,H,D,B,N
function sort(seq::LongSequence{DNAAlphabet{4}}; rev::Bool=false)
    sort(convert(Vector{DNA}, seq), by=degeneracy, rev=rev)
end

function is_palindrome(randomer)
    return occursin(randomer,reverse_complement(randomer))
end
"""
    isvalid(seq, sites)

Check if any of the sites appear in the sequence. Also check for palindromes by calling is palindrom

"""
function isvalid(seq, sites)
    if is_palindrome(seq)
        return false
    end
    for site in sites
        if occursin(site, seq)
            return false
        end
    end
    return true
end

"""
    find_valid_randomer(prefix, bases, sites)

Randomly select bases to add the prefix, ensuring no site
appears in the randomer.
"""
function find_valid_randomer(prefix, bases, sites)
    n = length(bases)
    pre_n = length(prefix)
    randomer = prefix * (dna"-" ^ n)
    for i = 1:n
        candidates=[];
        array=1:length(bases[i])
        candorder=shuffle(array)
        for j in 1:length(array)
        push!(candidates,bases[i][candorder[j]])
        end
        for cand in candidates
            randomer[pre_n+i] = cand
            if isvalid(randomer[1:pre_n+i], sites)
                break
            else
                randomer[pre_n+i] = DNA_Gap
            end
        end
        if randomer[pre_n+i] == DNA_Gap
            break
        end
    end
    return randomer
end

"""
    degeneracy(base::DNA[, uselog2=true])

Calculate the degeneracy of a single base. The degeneracy
is the number of bases in the code, so
    degeneracy(DNA_N) == 4
and
    degeneracy(DNA_A) == 1

If `uselog2`, the degeneracy is log2 transformed. By convention,
the degneracy of `DNA_Gap` is zero in both the log2-transformed
and the untransformed case.
"""
function degeneracy(base::DNA; uselog2=true)
    deg = 0.0
    if base == DNA_N
        deg = 4.0
    elseif base == DNA_A || base == DNA_C || base == DNA_G || base == DNA_T
        deg = 1.0
    elseif base == DNA_B || base == DNA_D || base == DNA_H || base == DNA_V
        deg = 3.0
    elseif (base == DNA_K || base == DNA_Y || base == DNA_S || base == DNA_W
            || base == DNA_R || base == DNA_M)
        deg = 2.0
    else # DNA_Gap
        deg = 0.0
    end

    if uselog2
        if base == DNA_Gap
            deg = 2^-100  #log2(0) is negative infinity, so we use something close to zero
        end

        return log2(deg)

    else
        return deg
    end
end

"""
    degeneracy(seq::LongSequence{DNAAlphabet{4}}; uselog2=true)

Calculate the degeneracy of a DNA sequence.
"""
function degeneracy(seq::LongSequence{DNAAlphabet{4}}; uselog2=true)
    if uselog2
        return sum(degeneracy.(seq, uselog2=true))
    else
        return prod(degeneracy.(seq, uselog2=false))
    end
end

function mRNA_multiobjective(randomer, mRNAs; indicies=[[] for i=1:10], b1=1,b2=1,overwrite_indicies=false, return_indicies=false,kwargs...)
    # If overwrite_indicies=false, the funciton will score the randomer as if the randomer were to be added, but will not actually add the randomer
    # If overwrite_indicies=true, then the function will add the randomer hit sites to the offical count
    # b1 = weight for uniformity score
    # b2 = weight for hits per unit length
    mRNAnum=length(mRNAs)
    gene_scores=zeros(mRNAnum);
    means=zeros(mRNAnum);
    stds=ones(mRNAnum);
    randomerlen=length(randomer);
    indicies_copy=deepcopy(indicies);
    for i=1:mRNAnum
        iteration=0
        index=approxsearchindex(mRNAs[i][1:end],randomer,0);
        if index > 0
            push!(indicies_copy[i],index)
        end
        iteration = iteration+1;
        while index > 0
            index=approxsearchindex(mRNAs[i][((indicies_copy[i][end]+1):end)],randomer,0);
            iteration=iteration+1;
            if index == 0
                break
            else
                push!(indicies_copy[i],index+indicies_copy[i][end])

            end
        end
        if length(indicies_copy[i])==0
            continue
        end
        dists=calculate_gap_distances(indicies_copy[i],length(mRNAs[i]),randomerlen)
        stds[i]=std(dists)/length(mRNAs[i])
        gene_scores[i]=1+b1*(1-stds[i])+b2*length(indicies_copy[i])/length(mRNAs[i]);
    end

    if overwrite_indicies && return_indicies
    return indicies_copy, b1, b2
    elseif ~overwrite_indicies &&  return_indicies
    return  indicies
    else  # by having return_indicies=false, you can just return the gene scores. This just makes the output of the function more flexible.
        return sum(gene_scores)
    end
end

function calculate_gap_distances(hit_indicies,genelen,randomerlen)
    dists=[]
    hit_indicies=sort(hit_indicies)
    push!(dists,hit_indicies[1])
    if length(hit_indicies)>1
        for i=2:length(hit_indicies)
            push!(dists,(hit_indicies[i]-hit_indicies[i-1]-randomerlen))
        end
    end
    push!(dists,(genelen-hit_indicies[end]-randomerlen))
    return dists
end

## Read in the list of sequences you want to exclude in the designed primers.
# Function finds every unique hexamer in the list of sequences and stores it as an array
#. For example, use list of rRNA and tRNA sequences. This funciton takes care of orientation. We end up using the reverse complement since we are finding primers that won't hybridize
## Example
#blocking_sites=read_blocking_sites(CSV.read("./SMU_UA159_rRNA_tRNA.csv"))
function read_blocking_sites(data; randomerlen=6)
    blocking_sites=[];
    for i =1:nrow(data)
        seq=reverse_complement(LongDNASeq(string(data[i,:Sequence])));
        for j=1:length(seq)-(randomerlen-1)
            if isvalid(seq[j:j+(randomerlen-1)],blocking_sites)
                push!(blocking_sites,seq[j:j+(randomerlen-1)])
            end
        end
    end
    return blocking_sites
end
# RNAs=read_rRNA_tRNA_list(CSV.read("./SMU_UA159_rRNA_tRNA.csv"))
function read_rRNA_tRNA_list(data)
    RNAs=[]
    for i=1:nrow(data)
        seq=reverse_complement(LongDNASeq(string(data[i,:Sequence])));
        if isvalid(seq,RNAs)
            push!(RNAs,seq)
        end
    end
    return RNAs
end
## Read in the list of sequences you want the designed primers to hybridize to
# Function takes care of the orientation, we want to end up using the reverse complmement.
## Example
# mRNAs=read_mRNA_list(CSV.read("./SMU_UA159_Genes.csv"))
function read_mRNA_list(data)
    mRNAs=[]
    for i=1:nrow(data)
        seq=reverse_complement(LongDNASeq(string(data[i,:mRNA_seq])));
        if isvalid(seq,mRNAs)
            push!(mRNAs,seq)
        end
    end
    return mRNAs
end

#Finds the number of bases as well as the GC content of the given file
# Example
# bases,GC_content=calculate_transcriptome_stats(read_mRNA_list(CSV.read("./SMU_UA159_Genes.csv")))
function calculate_transcriptome_stats(sequences)
    bases=0;  #number of bases in the file
    GC_count=0 # Count of G's and C's in file
    for i=1:length(sequences)
        bases += length(sequences[i]);
        comp=composition(sequences[i]);
        GC_count += comp[DNA_G] +comp[DNA_C];
    end
    GC_content= GC_count/bases*100;
    return bases,GC_content
end

#### Extra Analysis Funcitons

## Finds the edit distance distribution for a given designed primer to all of the blocking sites
function base_error_dist(randomer,sites)
    error_dist=[]
    for i in 0:length(randomer)
        count=0
        found_sites=[]
        for j in 1:length(sites)
            valid=approxsearchindex(randomer,sites[j],i)
            if valid == 1
                count += valid
                push!(found_sites,j)
            end
        end
        deleteat!(sites,found_sites)
        push!(error_dist,count)
    end

    return error_dist
end
# genes_hit,genes_missing,total_hits,uniformity_score=hit_stats(indicies,mRNAs,6)
function hit_stats(indicies,mRNAs,randomerlen)
    genes_hit=0;
    genes_missing=[]
    total_hits=0;
    stds=ones(length(indicies))
    for i=1:length(indicies);
        if length(indicies[i])>0
            genes_hit+=1;
            dists=calculate_gap_distances(indicies[i],length(mRNAs[i]),randomerlen)
            stds[i]=std(dists)/length(mRNAs[i]);
        else
            push!(genes_missing,i)
        end
        total_hits+=length(indicies[i]);
    end
    return genes_hit,genes_missing,total_hits,mean(1 .- stds)
end

function ID_genes_missing(data,genes_missing)
    missing_ID=[];
    for i in genes_missing
        push!(missing_ID,data[i,:New_ID])
    end
    return missing_ID
end

## Calculates the distribution number of randomers that hit each gene at least once. Not very useful.
function coverage_distribution(randomers, mRNA)
    coverage_dist=zeros(length(randomers)+1)
     for seq in mRNA
         count=0;
         for randomer in randomers
             if occursin(randomer, seq)
                 count+=1;
             end
         end
         coverage_dist[count+1]+=1;

     end
     return coverage_dist
end

# Calcualtes the number of times each gene is hit by all randomers in the pool. Useful for comparing the "between gene uniformity".
function gene_coverage_counts(randomers,mRNAfile)
    mRNAdata=CSV.read(mRNAfile,DataFrame);
    mRNAs=read_mRNA_list(mRNAdata)
    gene_hits=zeros(length(mRNAs))
    randomerlen=length(randomers[1]);
    for i in 1:length(mRNAs)
        counter=0;
        for j in 1:length(mRNAs[i])-randomerlen
            for k in 1:length(randomers)
                if occursin(randomers[k],mRNAs[i][j:j+randomerlen-1])
                    counter+=1
                end
            end
        end
        gene_hits[i]=counter
    end
    data=DataFrame(counts=gene_hits)
    return data

end
function randomer_coverage_counts(randomers,mRNAfile)
    mRNAdata=CSV.read(mRNAfile,DataFrame);
    mRNAs=read_mRNA_list(mRNAdata)
    randomer_hits=zeros(length(randomers))
    randomerlen=length(randomers[1]);
    for i in 1:length(randomers)
        counter=0;
        for j = 1:length(mRNAs)
            for k in 1:length(mRNAs[j])-randomerlen
                if occursin(randomers[i],mRNAs[j][k:k+randomerlen-1])
                    counter+=1
                end
            end
        end
        randomer_hits[i]=counter
    end
    data=DataFrame(randomers=randomers,counts=randomer_hits)
    return data
end

function dnaarray2stringarray(array)
    array2=[]
    for i=1:length(array)
        push!(array2,convert(String,array[i]))
    end
    return array2
end
function stringarray2dnaarray(array)
    array2=[]
    for i=1:length(array)
        push!(array2,LongDNASeq(array[i]))
    end
    return array2
end

function pooled_degeneracy(pool)
    deg=0;
    for randomer in pool
        deg +=degeneracy(randomer;uselog2=false);
    end
    return deg
end

function generate_random_pool(;randomerlen=6,randpoolsize=100,nucleotides=dna"ACGT")
    randpool=[]
    randomer=dna"-"^randomerlen
    for i = 1:randomerlen
        bases=shuffle(nucleotides)
        randomer[i]=bases[1];
    end
    push!(randpool,randomer)
    while length(randpool)<randpoolsize
        randomer=dna"-"^randomerlen
        for i = 1:randomerlen
            bases=shuffle(nucleotides)
            randomer[i]=bases[1];
        end
        check=true
        for j = 1:length(randpool)
            if randomer==randpool[j]
                check=false
                break
            end
        end
        if check
            push!(randpool,randomer)
        end
        if length(randpool)==length(nucleotides)^randomerlen
            break
        end
    end

    return randpool
end

function NSR_Brute_Force(species_name)
    rRNAfile=string("./Genome Data/",species_name,"_rRNA_tRNA.csv")
    mRNAfile=string("./Genome Data/",species_name,"_Genes.csv")
    sites=read_blocking_sites(CSV.read(rRNAfile,DataFrame));
    randomers=generate_random_pool(;randpoolsize=4^length(sites[1]))
    nsites=length(sites);
    del_indicies=[]
    for i=1:length(randomers)
        for j=1:nsites
            if randomers[i]==sites[j]
                push!(del_indicies,i)
                break
            end
        end
    end

    deleteat!(randomers, del_indicies)
    checkpoint=length(randomers)
    first_del=[];
    for j=1:length(randomers)
        if is_palindrome(randomers[j])
            push!(first_del,j)
        end
    end
    deleteat!(randomers,first_del)
    checkpoint=length(randomers)
    sec_del=[];
    rc_cands=[]
    rcs=reverse_complement.(randomers)
    for randomer in randomers
        if !isvalid(randomer,rcs)
            cand1=randomer
            cand2=reverse_complement(randomer)
            push!(rc_cands,cand1)
            push!(rc_cands,cand2)
        end
    end
    rc_cands=unique(rc_cands)
    rcpairs=length(rc_cands)/2;
    println("$rcpairs")
    hit_stats=randomer_coverage_counts(rc_cands,mRNAfile)
    for i=1:2:length(rc_cands)
        v,idx=findmin(hit_stats[i:i+1,2])
        del_cand=rc_cands[i+idx-1]
        push!(sec_del,findall(x->x==del_cand,randomers)[1])
    end
    sec_del=sort(unique(sec_del))
    deleteat!(randomers,sec_del)
    data=DataFrame(Sequence=randomers);
    outputfile=string("./Brute Force Pools V2/",species_name,"_NSR_Brute_Force_all_randomers.csv")
    CSV.write(outputfile,data)

end

function record_pool_size(species)
    n=length(species)
    poolsize=zeros(n)
    for i=1:n
        poolfile=string("./Brute Force Pools V2/",species[i],"_NSR_Brute_Force_all_randomers.csv");
        poolsize[i]=nrow(CSV.read(poolfile,DataFrame));
    end
    DF=DataFrame(species=species,poolsize=poolsize)
    outputfile="./Brute Force Pool Sizes V2.csv"
    CSV.write(outputfile,DF)
end
species=CSV.read("./Genome Data/Species_List.csv",DataFrame)
NSR_Brute_Force.(species[:Species])
record_pool_size(species[:Species])


text:
function wilkinson(n::Integer)
    var = Pol([0, 1])
    res = var-1
    @inbounds for i in 2:n
        res *= var-i
    end
    return res
end


text:
"""
Provides two functions, [`missingdocs`](@ref) and [`doctest`](@ref), for checking docs.
"""
module DocChecks

import ..Documenter:
    Builder,
    Documents,
    Expanders,
    Documenter,
    Utilities,
    Walkers

using Compat, DocStringExtensions

# Missing docstrings.
# -------------------

"""
$(SIGNATURES)

Checks that a [`Documents.Document`](@ref) contains all available docstrings that are
defined in the `modules` keyword passed to [`Documenter.makedocs`](@ref).

Prints out the name of each object that has not had its docs spliced into the document.
"""
function missingdocs(doc::Documents.Document)
    doc.user.checkdocs === :none && return
    println(" > checking for missing docstrings.")
    bindings = allbindings(doc.user.checkdocs, doc.user.modules)
    for object in keys(doc.internal.objects)
        if haskey(bindings, object.binding)
            signatures = bindings[object.binding]
            if object.signature ≡ Union{} || length(signatures) ≡ 1
                delete!(bindings, object.binding)
            elseif object.signature in signatures
                delete!(signatures, object.signature)
            end
        end
    end
    n = reduce(+, 0, map(length, values(bindings)))
    if n > 0
        b = IOBuffer()
        println(b, "$n docstring$(n ≡ 1 ? "" : "s") potentially missing:\n")
        for (binding, signatures) in bindings
            for sig in signatures
                println(b, "    $binding", sig ≡ Union{} ? "" : " :: $sig")
            end
        end
        push!(doc.internal.errors, :missing_docs)
        Utilities.warn(Utilities.takebuf_str(b))
    end
end

function allbindings(checkdocs::Symbol, mods)
    out = Dict{Utilities.Binding, Set{Type}}()
    for m in mods
        allbindings(checkdocs, m, out)
    end
    out
end

function allbindings(checkdocs::Symbol, mod::Module, out = Dict{Utilities.Binding, Set{Type}}())
    for (obj, doc) in meta(mod)
        isa(obj, ObjectIdDict) && continue
        local name = nameof(obj)
        local isexported = Base.isexported(mod, name)
        if checkdocs === :all || (isexported && checkdocs === :exports)
            out[Utilities.Binding(mod, name)] = Set(sigs(doc))
        end
    end
    out
end

if isdefined(Base.Docs, :META′) # 0.4
    meta(m) = isdefined(m, Docs.META′) ? Docs.meta(m) : ObjectIdDict()
else # 0.5
    meta(m) = Docs.meta(m)
end

if isleaftype(Function) # 0.4
    nameof(x::Function) = x.env.name
else # 0.5
    nameof(x::Function) = typeof(x).name.mt.name
end
nameof(b::Base.Docs.Binding) = b.var
nameof(x::DataType)          = x.name.name
nameof(m::Module)            = module_name(m)

if isdefined(Base.Docs, :MultiDoc) # 0.5
    sigs(x::Base.Docs.MultiDoc) = x.order
else # 0.4
    sigs(x::Base.Docs.FuncDoc) = x.order
    sigs(x::Base.Docs.TypeDoc) = x.order
end
sigs(::Any) = Type[Union{}]

# Julia code block testing.
# -------------------------

"""
$(SIGNATURES)

Traverses the document tree and tries to run each Julia code block encountered. Will abort
the document generation when an error is thrown. Use `doctest = false` keyword in
[`Documenter.makedocs`](@ref) to disable doctesting.
"""
function doctest(doc::Documents.Document)
    if doc.user.doctest
        println(" > running doctests.")
        for (src, page) in doc.internal.pages
            empty!(page.globals.meta)
            for element in page.elements
                page.globals.meta[:CurrentFile] = page.source
                Walkers.walk(page.globals.meta, page.mapping[element]) do block
                    doctest(block, page.globals.meta, doc, page)
                end
            end
        end
    else
        Utilities.warn("Skipped doctesting.")
    end
end

function __ans__!(m::Module, value)
    isdefined(m, :__ans__!) || eval(m, :(__ans__!(value) = global ans = value))
    return eval(m, Expr(:call, () -> m.__ans__!(value)))
end

function doctest(block::Markdown.Code, meta::Dict, doc::Documents.Document, page)
    local matched = Utilities.nullmatch(r"jldoctest[ ]?(.*)$", block.language)
    if !isnull(matched)
        # Define new module or reuse an old one from this page if we have a named doctest.
        local name = Utilities.getmatch(matched, 1)
        local sym = isempty(name) ? gensym("doctest-") : Symbol("doctest-", name)
        local sandbox = get!(page.globals.meta, sym) do
            newmod = Module(sym)
            eval(newmod, :(eval(x) = Core.eval(current_module(), x)))
            eval(newmod, :(eval(m, x) = Core.eval(m, x)))
            newmod
        end
        # Normalise line endings.
        local code = replace(block.code, "\r\n", "\n")
        if haskey(meta, :DocTestSetup)
            expr = meta[:DocTestSetup]
            Meta.isexpr(expr, :block) && (expr.head = :toplevel)
            eval(sandbox, expr)
        end
        if ismatch(r"^julia> "m, code)
            eval_repl(code, sandbox, meta, doc, page)
            block.language = "julia-repl"
        elseif ismatch(r"^# output$"m, code)
            eval_script(code, sandbox, meta, doc, page)
            block.language = "julia"
        else
            push!(doc.internal.errors, :doctest)
            Utilities.warn(
                """
                Invalid doctest block. Requires `julia> ` or `# output` in '$(meta[:CurrentFile])'

                ```jldoctest
                $(code)
                ```
                """
            )
        end
    end
    false
end
doctest(block, meta::Dict, doc::Documents.Document, page) = true

function doctest(block::Markdown.MD, meta::Dict, doc::Documents.Document, page)
    haskey(block.meta, :path) && (meta[:CurrentFile] = block.meta[:path])
    return true
end

# Doctest evaluation.

type Result
    code   :: Compat.String # The entire code block that is being tested.
    input  :: Compat.String # Part of `code` representing the current input.
    output :: Compat.String # Part of `code` representing the current expected output.
    file   :: Compat.String # File in which the doctest is written. Either `.md` or `.jl`.
    value  :: Any        # The value returned when evaluating `input`.
    hide   :: Bool       # Semi-colon suppressing the output?
    stdout :: IOBuffer   # Redirected STDOUT/STDERR gets sent here.
    bt     :: Vector     # Backtrace when an error is thrown.

    function Result(code, input, output, file)
        new(code, input, rstrip(output, '\n'), file, nothing, false, IOBuffer())
    end
end

function eval_repl(code, sandbox, meta::Dict, doc::Documents.Document, page)
    for (input, output) in repl_splitter(code)
        result = Result(code, input, output, meta[:CurrentFile])
        for (ex, str) in Utilities.parseblock(input, doc, page; keywords = false)
            # Input containing a semi-colon gets suppressed in the final output.
            result.hide = ends_with_semicolon(str)
            (value, success, backtrace, text) = Utilities.withoutput() do
                disable_color() do
                    Core.eval(sandbox, ex)
                end
            end
            result.value = value
            print(result.stdout, text)
            if success
                # Redefine the magic `ans` binding available in the REPL.
                __ans__!(sandbox, result.value)
            else
                result.bt = backtrace
            end
        end
        checkresult(sandbox, result, doc)
    end
end

function eval_script(code, sandbox, meta::Dict, doc::Documents.Document, page)
    # TODO: decide whether to keep `# output` syntax for this. It's a bit ugly.
    #       Maybe use double blank lines, i.e.
    #
    #
    #       to mark `input`/`output` separation.
    input, output = split(code, "\n# output\n", limit = 2)
    result = Result(code, "", output, meta[:CurrentFile])
    for (ex, str) in Utilities.parseblock(input, doc, page; keywords = false)
        (value, success, backtrace, text) = Utilities.withoutput() do
            Core.eval(sandbox, ex)
        end
        result.value = value
        print(result.stdout, text)
        if !success
            result.bt = backtrace
            break
        end
    end
    checkresult(sandbox, result, doc)
end

# Regex used here to replace gensym'd module names could probably use improvements.
function checkresult(sandbox::Module, result::Result, doc::Documents.Document)
    local mod_regex = Regex("(Symbol\\(\"$(sandbox)\"\\)|$(sandbox))[,.]")
    if isdefined(result, :bt) # An error was thrown and we have a backtrace.
        # To avoid dealing with path/line number issues in backtraces we use `[...]` to
        # mark ignored output from an error message. Only the text prior to it is used to
        # test for doctest success/failure.
        head = replace(split(result.output, "\n[...]"; limit = 2)[1], mod_regex, "")
        str  = replace(error_to_string(result.stdout, result.value, result.bt), mod_regex, "")
        # Since checking for the prefix of an error won't catch the empty case we need
        # to check that manually with `isempty`.
        if isempty(head) || !startswith(str, head)
            report(result, str, doc)
        end
    else
        value = result.hide ? nothing : result.value # `;` hides output.
        str = replace(result_to_string(result.stdout, value), mod_regex, "")
        # Replace a standalone module name with `Main`.
        str = replace(str, Regex(string(sandbox)), "Main")
        output = replace(strip(sanitise(IOBuffer(result.output))), mod_regex, "")
        strip(str) == output || report(result, str, doc)
    end
    return nothing
end

# from base/REPL.jl
function ends_with_semicolon(line)
    match = rsearch(line, ';')
    if match != 0
        for c in line[(match+1):end]
            isspace(c) || return c == '#'
        end
        return true
    end
    return false
end

# Display doctesting results.

function result_to_string(buf, value)
    dis = text_display(buf)
    value === nothing || disable_color() do
        eval(Expr(:call, display, dis, QuoteNode(value)))
    end
    sanitise(buf)
end

if VERSION < v"0.5.0-dev+4305"
    text_display(buf) = TextDisplay(buf)
else
    text_display(buf) = TextDisplay(IOContext(buf, :limit => true))
end

funcsym() = CAN_INLINE[] ? :disable_color : :eval

if isdefined(Base.REPL, :ip_matches_func)
    function error_to_string(buf, er, bt)
        local fs = funcsym()
        # Remove unimportant backtrace info.
        local index = findlast(ptr -> Base.REPL.ip_matches_func(ptr, fs), bt)
        # Print a REPL-like error message.
        disable_color() do
            print(buf, "ERROR: ")
            showerror(buf, er, index == 0 ? bt : bt[1:(index - 1)])
        end
        sanitise(buf)
    end
else
    # Compat for Julia 0.4.
    function error_to_string(buf, er, bt)
        local fs = funcsym()
        disable_color() do
            print(buf, "ERROR: ")
            try
                Base.showerror(buf, er)
            finally
                Base.show_backtrace(buf, fs, bt, 1:typemax(Int))
            end
        end
        sanitise(buf)
    end
end

# Strip trailing whitespace and remove terminal colors.
function sanitise(buffer)
    out = IOBuffer()
    for line in eachline(seekstart(buffer))
        println(out, rstrip(line))
    end
    remove_term_colors(rstrip(Utilities.takebuf_str(out), '\n'))
end

import .Utilities.TextDiff

function report(result::Result, str, doc::Documents.Document)
    local buffer = IOBuffer()
    println(buffer, "=====[Test Error]", "="^30)
    println(buffer)
    print_with_color(:cyan, buffer, "> File: ", result.file, "\n")
    print_with_color(:cyan, buffer, "\n> Code block:\n")
    println(buffer, "\n```jldoctest")
    println(buffer, result.code)
    println(buffer, "```")
    if !isempty(result.input)
        print_with_color(:cyan, buffer, "\n> Subexpression:\n")
        print_indented(buffer, result.input; indent = 4)
    end
    local warning = Base.have_color ? "" : " (REQUIRES COLOR)"
    print_with_color(:cyan, buffer, "\n> Output Diff", warning, ":\n\n")
    local diff = TextDiff.Diff{TextDiff.Words}(result.output, rstrip(str))
    Utilities.TextDiff.showdiff(buffer, diff)
    println(buffer, "\n\n", "=====[End Error]=", "="^30)
    push!(doc.internal.errors, :doctest)
    print_with_color(:normal, Utilities.takebuf_str(buffer))
end

function print_indented(buffer::IO, str::AbstractString; indent = 4)
    println(buffer)
    for line in split(str, '\n')
        println(buffer, " "^indent, line)
    end
end

# Remove terminal colors.

const TERM_COLOR_REGEX = r"\e\[[0-9;]*m"
remove_term_colors(s) = replace(s, TERM_COLOR_REGEX, "")

# REPL doctest splitter.

const PROMPT_REGEX = r"^julia> (.*)$"
const SOURCE_REGEX = r"^       (.*)$"

function repl_splitter(code)
    lines  = split(string(code, "\n"), '\n')
    input  = Compat.String[]
    output = Compat.String[]
    buffer = IOBuffer()
    while !isempty(lines)
        line = shift!(lines)
        # REPL code blocks may contain leading lines with comments. Drop them.
        # TODO: handle multiline comments?
        startswith(line, '#') && continue
        prompt = Utilities.nullmatch(PROMPT_REGEX, line)
        if isnull(prompt)
            source = Utilities.nullmatch(SOURCE_REGEX, line)
            if isnull(source)
                savebuffer!(input, buffer)
                println(buffer, line)
                takeuntil!(PROMPT_REGEX, buffer, lines)
            else
                println(buffer, Utilities.getmatch(source, 1))
            end
        else
            savebuffer!(output, buffer)
            println(buffer, Utilities.getmatch(prompt, 1))
        end
    end
    savebuffer!(output, buffer)
    zip(input, output)
end

function savebuffer!(out, buf)
    n = nb_available(seekstart(buf))
    n > 0 ? push!(out, rstrip(Utilities.takebuf_str(buf))) : out
end

function takeuntil!(r, buf, lines)
    while !isempty(lines)
        line = lines[1]
        if isnull(Utilities.nullmatch(r, line))
            println(buf, shift!(lines))
        else
            break
        end
    end
end

# Footnote checks.
# ----------------

if isdefined(Base.Markdown, :Footnote)
    function footnotes(doc::Documents.Document)
        println(" > checking footnote links.")
        # A mapping of footnote ids to a tuple counter of how many footnote references and
        # footnote bodies have been found.
        #
        # For all ids the final result should be `(N, 1)` where `N > 1`, i.e. one or more
        # footnote references and a single footnote body.
        local footnotes = Dict{Documents.Page, Dict{Compat.String, Tuple{Int, Int}}}()
        for (src, page) in doc.internal.pages
            empty!(page.globals.meta)
            local orphans = Dict{Compat.String, Tuple{Int, Int}}()
            for element in page.elements
                Walkers.walk(page.globals.meta, page.mapping[element]) do block
                    footnote(block, orphans)
                end
            end
            footnotes[page] = orphans
        end
        for (page, orphans) in footnotes
            for (id, (ids, bodies)) in orphans
                # Multiple footnote bodies.
                if bodies > 1
                    push!(doc.internal.errors, :footnote)
                    Utilities.warn(page.source, "Footnote '$id' has $bodies bodies.")
                end
                # No footnote references for an id.
                if ids === 0
                    push!(doc.internal.errors, :footnote)
                    Utilities.warn(page.source, "Unused footnote named '$id'.")
                end
                # No footnote bodies for an id.
                if bodies === 0
                    push!(doc.internal.errors, :footnote)
                    Utilities.warn(page.source, "No footnotes found for '$id'.")
                end
            end
        end
    end

    function footnote(fn::Markdown.Footnote, orphans::Dict)
        ids, bodies = get(orphans, fn.id, (0, 0))
        if fn.text === nothing
            # Footnote references: syntax `[^1]`.
            orphans[fn.id] = (ids + 1, bodies)
            return false # No more footnotes inside footnote references.
        else
            # Footnote body: syntax `[^1]:`.
            orphans[fn.id] = (ids, bodies + 1)
            return true # Might be footnotes inside footnote bodies.
        end
    end

    footnote(other, orphans::Dict) = true
else
    footnotes(doc::Documents.Document) = nothing
end

# Link Checks.
# ------------

hascurl() = (try; success(`curl --version`); catch err; false; end)

function linkcheck(doc::Documents.Document)
    if doc.user.linkcheck
        if hascurl()
            println(" > checking external URLs:")
            for (src, page) in doc.internal.pages
                println("   - ", src)
                for element in page.elements
                    Walkers.walk(page.globals.meta, page.mapping[element]) do block
                        linkcheck(block, doc)
                    end
                end
            end
        else
            push!(doc.internal.errors, :linkcheck)
            Utilities.warn("linkcheck requires `curl`.")
        end
    end
    return nothing
end

function linkcheck(link::Base.Markdown.Link, doc::Documents.Document)
    local INDENT = " "^6

    # first, make sure we're not supposed to ignore this link
    for r in doc.user.linkcheck_ignore
        if linkcheck_ismatch(r, link.url)
            print_with_color(:normal, INDENT, "--- ", link.url, "\n")
            return false
        end
    end

    if !haskey(doc.internal.locallinks, link)
        local result
        try
            result = readstring(`curl -sI $(link.url)`)
        catch err
            push!(doc.internal.errors, :linkcheck)
            Utilities.warn("`curl -sI $(link.url)` failed:\n\n$(err)")
            return false
        end
        local STATUS_REGEX   = r"^HTTP/1.1 (\d+) (.+)$"m
        if ismatch(STATUS_REGEX, result)
            local status = parse(Int, match(STATUS_REGEX, result).captures[1])
            if status < 300
                print_with_color(:green, INDENT, "$(status) ", link.url, "\n")
            elseif status < 400
                local LOCATION_REGEX = r"^Location: (.+)$"m
                if ismatch(LOCATION_REGEX, result)
                    local location = strip(match(LOCATION_REGEX, result).captures[1])
                    print_with_color(:yellow, INDENT, "$(status) ", link.url, "\n")
                    print_with_color(:yellow, INDENT, " -> ", location, "\n\n")
                else
                    print_with_color(:yellow, INDENT, "$(status) ", link.url, "\n")
                end
            else
                push!(doc.internal.errors, :linkcheck)
                print_with_color(:red, INDENT, "$(status) ", link.url, "\n")
            end
        else
            push!(doc.internal.errors, :linkcheck)
            Utilities.warn("invalid result returned by `curl -sI $(link.url)`:\n\n$(result)")
        end
    end
    return false
end
linkcheck(other, doc::Documents.Document) = true

linkcheck_ismatch(r::String, url) = (url == r)
linkcheck_ismatch(r::Regex, url) = ismatch(r, url)

function disable_color(func)
    orig = setcolor!(false)
    try
        func()
    finally
        setcolor!(orig)
    end
end

const CAN_INLINE = Ref(true)
function __init__()
    global setcolor! = eval(Base, :(x -> (y = have_color; global have_color = x; y)))
    CAN_INLINE[] = Base.JLOptions().can_inline == 0 ? false : true
end

end


text:
using DifferentialEquations
using Plots

function seir_ode(dY,Y,p,t)
 dY[1] = p[4]-p[1]*Y[1]*Y[3]-p[4]*Y[1]
 dY[2] = p[1]*Y[1]*Y[3]-(p[2]+p[4])*Y[2]
 dY[3] = p[2]*Y[2] - (p[3]+p[4])*Y[3]
end

par=[520/365,1/60,1/30,774835/(65640000*365)]
init=[0.8,0.1,0.1]
tspan=(0.0,365.0)

seir_prob = ODEProblem(seir_ode,init,tspan,par)

sol=solve(seir_prob);

# Plot
R=ones(1,size(sol,2))-sum(sol,1);

plot(sol.t,[sol',R'],xlabel="Time",ylabel="Proportion")

max_stars_repo_name: epimodels/epicookbook

max_issues_repo_name: epimodels/epicookbook

max_forks_repo_name: epimodels/epicookbook


text:
@inline function sampleCategoricalSorted!(vs::Vector{Int64}, p::Vector{Float64},
  unifs::Vector{Float64}, Fs::Vector{Float64},
  rng::RNG = GLOBAL_RNG) where RNG <: AbstractRNG
  sampleSortedUniforms!(unifs, rng)
  cumsum!(Fs, p)
  @inbounds maxFs = Fs[length(p)]
  j = 1
  for i = 1:length(vs)
    @inbounds while maxFs * unifs[i] > Fs[j]
      j += 1
    end
    @inbounds vs[i] = j
  end
end

@inline function sampleCategoricalSorted!(vs::Vector{Int64}, p::Vector{Float64},
  rng::RNG = GLOBAL_RNG) where RNG <: AbstractRNG
  unifs::Vector{Float64} = Vector{Float64}(undef, length(vs))
  Fs::Vector{Float64} = Vector{Float64}(undef, length(p))
  sampleCategoricalSorted!(vs, p, unifs, Fs, rng)
end

@inline function sampleCategoricalSorted(n::Int64, p::Vector{Float64},
  rng::RNG = GLOBAL_RNG) where RNG <: AbstractRNG
  vs::Vector{Int64} = Vector{Int64}(undef, n)
  sampleCategoricalSorted!(vs, p, rng)
  return vs
end

@inline function sampleCategorical(n::Int64, p::Vector{Float64},
  rng::RNG = GLOBAL_RNG) where RNG <: AbstractRNG
  vs::Vector{Int64} = sampleCategoricalSorted(n, p)
  shuffle!(rng, vs)
  return vs
end

@inline function sampleCategorical(ws::Vector{Float64}, sws::Float64,
  rng::RNG = GLOBAL_RNG) where RNG <: AbstractRNG
  u::Float64 = rand(rng) * sws
  i::Int64 = 1
  v::Float64 = ws[1]
  while u > v
    i += 1
    @inbounds v += ws[i]
  end
  return i
end

@inline function sampleCategorical(ws::Vector{Float64},
  rng::RNG = GLOBAL_RNG) where RNG <: AbstractRNG
  return sampleCategorical(ws, sum(ws), rng)
end


text:
###########################################################
# This is my module that contains some wrapper functions.
# Author: Tokuma Suzuki
###########################################################

using LinearAlgebra, SparseArrays

function speye(size, dtype=Float64)
    """
    Return sparse identity matrix.

    This function needs LinearAlgebra and SparseArrays.
    Arguments:
    size: Int64
    dtype: keywords, Float64 or Int64
    """

    return sparse(Matrix{dtype}(I, size, size))
end

function linspace(start,stop,size=50)
    """

    Return linealy spaced 1d array

    Arguments:
    start: Real
    end: Real
    size: Int
    """

    return collect(LinRange(start,stop,size))
end


text:
using DrWatson
@quickactivate
using ArgParse
using GenerativeAD
import StatsBase: fit!, predict
using StatsBase
using BSON
using Flux
using GenerativeModels

s = ArgParseSettings()
@add_arg_table! s begin
   "max_seed"
		default = 1
		arg_type = Int
		help = "seed"
	"dataset"
		default = "MNIST"
		arg_type = String
		help = "dataset"
	"anomaly_classes"
		arg_type = Int
		default = 10
		help = "number of anomaly classes"
	"method"
		arg_type = String
		default = "leave-one-out"
		help = "method for data creation -> \"leave-one-out\" or \"leave-one-in\" "
    "contamination"
    	arg_type = Float64
    	help = "contamination rate of training data"
    	default = 0.0
end
parsed_args = parse_args(ARGS, s)
@unpack dataset, max_seed, anomaly_classes, method, contamination = parsed_args

#######################################################################################
################ THIS PART IS TO BE PROVIDED FOR EACH MODEL SEPARATELY ################

modelname = "fmgan"

# sample parameters, should return a Dict of model kwargs
"""
	sample_params()

Should return a named tuple that contains a sample of model parameters.
"""
function sample_params()
	# first sample the number of layers
	nlayers = rand(2:4)
	kernelsizes = reverse((3,5,7,9)[1:nlayers])
	channels = reverse((16,32,64,128)[1:nlayers])
	scalings = reverse((1,2,2,2)[1:nlayers])

	par_vec = (2 .^(3:8), 10f0 .^(-4:-3), 2 .^ (5:7), ["relu", "swish", "tanh"], 1:Int(1e8), 10f0 .^ (-3:3))
	argnames = (:zdim, :lr, :batchsize, :activation, :init_seed, :alpha,)
	parameters = (;zip(argnames, map(x->sample(x, 1)[1], par_vec))...)
	return merge(parameters, (nlayers=nlayers, kernelsizes=kernelsizes,
		channels=channels, scalings=scalings))
end
batch_score(scoref, model, x, batchsize=512) =
	vcat(map(y->vec(cpu(scoref(model, gpu(Array(y))))), Flux.Data.DataLoader(x, batchsize=batchsize))...)
"""
	fit(data, parameters)

This is the most important function - returns `training_info` and a tuple or a vector of tuples `(score_fun, final_parameters)`.
`training_info` contains additional information on the training process that should be saved, the same for all anomaly score functions.
Each element of the return vector contains a specific anomaly score function - there can be multiple for each trained model.
Final parameters is a named tuple of names and parameter values that are used for creation of the savefile name.
"""
function fit(data, parameters)
	# construct model - constructor should only accept kwargs
	idim = size(data[1][1])[1:3]

	# construct model - constructor should only accept kwargs
	model = GenerativeAD.Models.conv_gan_constructor(;idim=idim, parameters...) |> gpu

	# setup the loss functions
	function gloss(m, x)
	        # move x to gpu
        	x = gpu(Array(x))
	        z = gpu(rand(cpu(m.prior), size(x,ndims(x))))

        	# generator loss
	        gl = GenerativeAD.Models.gloss(m.discriminator.mapping,
        	        m.generator.mapping,z)

	        # fm loss
        	h = m.discriminator.mapping[1:end-3]
	        hx = h(x)
        	hz = h(m.generator.mapping(z))
	        fml = Flux.mse(hx, hz)

        	parameters.alpha*gl + fml
	end
	gloss(m, x, batchsize::Int) =
        	mean(map(y->gloss(m,y), Flux.Data.DataLoader(x, batchsize=batchsize)))
	function dloss(m, x)
        	x = gpu(Array(x))
	        z = gpu(rand(cpu(m.prior), size(x,ndims(x))))
        	GenerativeAD.Models.dloss(m.discriminator.mapping,m.generator.mapping,x,z)
	end
	dloss(m, x, batchsize::Int) =
        	mean(map(y->dloss(m,y), Flux.Data.DataLoader(x, batchsize=batchsize)))

	# set number of max iterations apropriately
	max_iter = 5000 # this should be enough

	# fit train data
	try
		global info, fit_t, _, _, _ = @timed fit!(model, data, gloss, dloss; max_iters=10000,
			max_train_time=23*3600/max_seed/anomaly_classes/4, patience=200,
			check_interval=10,
			usegpu=true, parameters...)
	catch e
		# return an empty array if fit fails so nothing is computed
		@info "Failed training due to \n$e"
		return (fit_t = NaN, history=nothing, npars=nothing, model=nothing), []
	end
	model = info.model

	# construct return information - put e.g. the model structure here for generative models
	training_info = (
		fit_t = fit_t,
		history = info.history,
		npars = info.npars,
		model = model |> cpu
		)

	# now return the different scoring functions
	training_info, [
		(x -> 1f0 .- batch_score(GenerativeAD.Models.discriminate, model, x), parameters)
		]
end

####################################################################
################ THIS PART IS COMMON FOR ALL MODELS ################
# only execute this if run directly - so it can be included in other files
if abspath(PROGRAM_FILE) == @__FILE__
	# set a maximum for parameter sampling retries
	try_counter = 0
	max_tries = 10*max_seed
	cont_string = (contamination == 0.0) ? "" : "_contamination-$contamination"
	while try_counter < max_tries
		parameters = sample_params()

		for seed in 1:max_seed
			for i in 1:anomaly_classes
				savepath = datadir("experiments/images_$(method)$cont_string/$(modelname)/$(dataset)/ac=$(i)/seed=$(seed)")
				mkpath(savepath)

				# get data
				data = GenerativeAD.load_data(dataset, seed=seed, anomaly_class_ind=i, method=method, contamination=contamination)

				# edit parameters
				edited_parameters = GenerativeAD.edit_params(data, parameters)

				@info "Trying to fit $modelname on $dataset with parameters $(edited_parameters)..."
				@info "Train/validation/test splits: $(size(data[1][1], 4)) | $(size(data[2][1], 4)) | $(size(data[3][1], 4))"
				@info "Number of features: $(size(data[1][1])[1:3])"

				# check if a combination of parameters and seed alread exists
				if GenerativeAD.check_params(savepath, edited_parameters)
					# fit
					training_info, results = fit(data, edited_parameters)

					# save the model separately
					if training_info.model != nothing
						tagsave(joinpath(savepath, savename("model", edited_parameters, "bson", digits=5)),
							Dict("model"=>training_info.model,
								 "fit_t"=>training_info.fit_t,
								 "history"=>training_info.history,
								 "parameters"=>edited_parameters
								 ),
							safe = true)
						training_info = merge(training_info,
							(model=nothing,))
					end

					# here define what additional info should be saved together with parameters, scores, labels and predict times
					save_entries = merge(training_info, (modelname = modelname, seed = seed, dataset = dataset, anomaly_class = i,
					contamination=contamination))

					# now loop over all anomaly score funs
					for result in results
						GenerativeAD.experiment(result..., data, savepath; save_entries...)
					end
					global try_counter = max_tries + 1
				else
					@info "Model already present, trying new hyperparameters..."
					global try_counter += 1
				end
			end
		end
	end
	(try_counter == max_tries) ? (@info "Reached $(max_tries) tries, giving up.") : nothing
end


text:
using Documenter
using PeaceFounder
makedocs(sitename="PeaceFounder.jl",pages = ["index.md"])

deploydocs(
     repo = "github.com/PeaceFounder/PeaceFounder.jl.git",
 )

max_stars_repo_name: akels/DemocracyCredit

max_issues_repo_name: akels/DemocracyCredit

max_forks_repo_name: akels/DemocracyCredit


text:
# this is a custom fork of PkgTemplates
module Templates

using LibGit2: LibGit2, GitConfig, GitReference, GitRemote, GitRepo, delete_branch
using UUIDs: uuid4
using Mustache: render
using Configurations: Configurations, field_default, @option, from_dict
using OrderedCollections: OrderedDict
using Pkg: Pkg, PackageSpec
using TOML
using Comonicon.Parse: default_name
using InteractiveUtils: subtypes
using Dates: month, today, year

using ..IonBase: templates
using ..PkgCmd
using ..Options

export Template, PackagePlan,
    AppVeyor,
    BlueStyleBadge,
    CirrusCI,
    Citation,
    Codecov,
    ColPracBadge,
    CompatHelper,
    Coveralls,
    Documenter,
    DroneCI,
    Git,
    GitHubActions,
    GitLabCI,
    License,
    Logo,
    NoDeploy,
    ProjectFile,
    Readme,
    Secret,
    SrcDir,
    TagBot,
    Tests,
    TravisCI,
    Comonicon,
    SystemImage

abstract type Plugin end

struct Template
    name::String
    plugins::Vector{Plugin}
end

function Template(file::String)
    d = TOML.parsefile(file)
    haskey(d, "name") || throw(ArgumentError("template must have field name"))
    plugins = collect_plugins(d)
    return Template(d["name"], plugins)
end

function Configurations.toml(to_toml, io::IO, t::Template; sorted::Bool=false, by=identity)
    d = OrderedDict{String, Any}("name" => t.name)
    for plugin in t.plugins
        P = typeof(plugin)
        alias = Configurations.alias(P)
        name = alias === nothing ? string(nameof(P)) : alias
        plugin_dict = Configurations.dictionalize(plugin)
        d[name] = plugin_dict
    end
    TOML.print(to_toml, io, d; sorted=sorted, by=by)
    return
end

function collect_plugins!(plugins::Vector{Any}, ::Type{T}, d::AbstractDict{String}) where T
    for each in subtypes(T)
        if isabstracttype(each)
            collect_plugins!(plugins, each, d)
            continue
        end

        alias = Configurations.alias(each)
        name = alias === nothing ? string(nameof(each)) : alias
        if name in keys(d)
            push!(plugins, from_dict(each, d[name]))
        end
    end
    return plugins
end

function collect_plugins(d::AbstractDict{String})
    return collect_plugins!([], Plugin, d)
end

struct PackagePlan
    template::Template
    name::String
    user::String
    authors::Vector{String}
    host::String
    julia::VersionNumber
    ion::Options.Ion

    function PackagePlan(t::Template, name::String, user::String, authors::Vector{String}, host::String, julia::VersionNumber, ion::Options.Ion = Options.read())
        endswith(name, ".jl") && (name = name[1:end-3])
        host = replace(host, r".*://" => "")
        new(t, name, user, authors, host, julia, ion)
    end
end

function PackagePlan(template::String, name::String, user::String, authors::Vector{String}, host::String, julia::VersionNumber, ion::Options.Ion = Options.read())
    haskey(ion.templates, template) || throw(ArgumentError("cannot find template: $template"))
    t = Template(ion.templates[template])
    return PackagePlan(t, name, user, authors, host, julia, ion)
end

function create(pkg::PackagePlan, path::String=pwd(), force::Bool=false)
    pkg_dir = joinpath(abspath(expanduser(path)), pkg.name)
    ispath(pkg_dir) && !force && throw(ArgumentError("$pkg_dir already exists"))
    if force && ispath(pkg_dir)
        rm(pkg_dir; force=true, recursive=true)
    end
    mkpath(pkg_dir)

    try
        foreach((prehook, hook, posthook)) do h
            @info "Running $(nameof(h))s"
            foreach(sort(pkg.template.plugins; by=p -> priority(p, h), rev=true)) do p
                h(p, pkg, pkg_dir)
            end
        end
    catch
        rm(pkg_dir; recursive=true, force=true)
        rethrow()
    end

    @info "New package is at $pkg_dir"
end

hasplugin(t::PackagePlan, f::Function) = any(f, t.template.plugins)
hasplugin(t::PackagePlan, ::Type{T}) where T <: Plugin = hasplugin(t, p -> p isa T)

"""
    getplugin(t::PackagePlan, ::Type{T<:Plugin}) -> Union{T, Nothing}

Get the plugin of type `T` from the template `t`, if it's present.
"""
function getplugin(t::PackagePlan, ::Type{T}) where T <: Plugin
    i = findfirst(p -> p isa T, t.template.plugins)
    return i === nothing ? nothing : t.template.plugins[i]
end

function default_branch(t::PackagePlan)
    git = getplugin(t, Git)
    return git === nothing ? nothing : git.branch
end

function find_username(ion::Options.Ion=Options.read())::String
    username = LibGit2.getconfig("github.user", ion.username)
    isempty(username) || return username
    input = Base.prompt("Enter value for 'username' (String, required)")
    input === nothing && cmd_error("invalid username")
    ion.username = String(input)
    return ion.username
end

function default_authors()
    name = LibGit2.getconfig("user.name", "")
    isempty(name) && return ["contributors"]
    email = LibGit2.getconfig("user.email", "")
    authors = isempty(email) ? name : "$name <$email>"
    return ["$authors and contributors"]
end

include("plugin.jl")

end

"""
create a project or package.

# Arguments

- `path`: path of the project you want to create

# Options

- `--user <name>`: your GitHub user name for this package.
- `--template <template name>`: template name.

# Flags

- `-f, --force`: force create a new project, remove `path` if it exists.
"""
@cast function create(path::String; user::String="", template::String="basic", authors::String="", host::String="github.com", force::Bool=false)
    ion = Options.read()
    isempty(user) && (user = Templates.find_username(ion))
    julia = Options.active_julia_version(ion)
    authors = isempty(authors) ? Templates.default_authors() : map(x->String(strip(x)), split(authors, ","))
    pkg = Templates.PackagePlan(template, basename(path), user, authors, host, julia, ion)
    Templates.create(pkg, isempty(dirname(path)) ? pwd() : dirname(path), force)
    Options.dump(ion)
    return
end


text:
using CoordinateTransformations

function (t::Translation)(p::IAEAParticle)
    pos = t(position(p))
    set_position(p, pos)
end
function (t::LinearMap)(p::IAEAParticle)
    pos = t(position(p))
    dir = t(direction(p))
    set_position_direction(p, pos, dir)
end
function (t::AffineMap)(p::IAEAParticle)
    pos = t(position(p))
    dir = t.linear*direction(p)
    set_position_direction(p, pos, dir)
end