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

using Markdown
using InteractiveUtils

# ╔═╡ 4ab649c8-743f-11ec-181b-f3e7e7ea7e82
begin
	using PhysicalConstants.CODATA2018: G, ħ, c_0
	using Unitful
	using Images

	md"""
	# Homework #1

	Eric Nguyen
	"""
end

# ╔═╡ d72e1ae3-6c5b-49a5-b45a-e8fe2c2f1f67
md"""
### Problem 1

First, we want to show that the product of pressure ``P`` and volume ``V`` has the dimension of energy, i.e., ``[P][V] = [E]``.

The dimensions of energy ``[E]`` can be found using ``E = mc^2`` where ``m`` is mass and ``c`` is the speed of light. ``[m] = M`` and ``[c]^2 = [v]^2 = [LT^{-1}]^2 = L^2T^{-2}`` so

$[E] = ML^2T^{-2}.$

The dimensions of pressure ``[P]`` can be found using ``\displaystyle p = \frac{F}{A}`` where ``F`` is force and ``A`` is area.
``[F] = [m][a] = MLT^{-2}`` and ``[A]^{-1} = [[ℓ][w]]^{-1} = [L^2]^{-1} = L^{-2}`` so

$[P] = [MLT^{-2}] [L^{-2}] = ML^{-1}T^{-2}.$

The dimensions of volume ``[V]`` can be found using ``V = ℓwh`` where ``ℓ, w, h`` are of dimension ``L``.
Then

$[V] = L^3.$

Multiplying the dimensions ``[P]`` and ``[V]`` we can show that the product ``PV`` has the dimension of energy,

$\begin{align*}
[P][V] &= [ML^{-1}T^{-2}][L^3] \\
&= ML^2T^{-2} \\
&= [E].
\end{align*}$

Using ``[PV] = [E]`` and the ideal gas law ``PV = NkT``, where ``N`` is the number of gas molecules and ``T`` is temperature in Kelvin, we can find the SI units of Boltzmann's constant ``k``

$\begin{align*}
PV &= NkT \\
k &= \frac{PV}{NT} \\
\implies [k] &= \frac{[E]}{[NT]} \\
&= \frac{ML^2T^{-2}}{Θ}
\end{align*}$

where ``Θ`` represents the dimension of temperature.
The corresponding SI units for ``M``, ``L``, ``T`` and ``Θ`` are ``kg``, ``m``, ``s``, and ``K``, respectively.
Thus the SI units of Boltzmann's constant ``k`` are ``\displaystyle \frac{kg ⋅ m^2}{s^2 ⋅ K}``.
"""

# ╔═╡ 1ba01821-dfb6-44b5-80f2-a131e01b9e8b
md"""
### Problem 2

**(a).** The energy scale for classical oscillations in terms of ``m``, ``k``, and ``A`` can be written as

$E = m^x k^y A^y \tag{1}$

The dimensions of the stiffness ``k`` can be found using ``\displaystyle k = \frac{F}{x}`` where ``F`` is force and ``x`` is displacement,

$[k] = \frac{[F]}{[x]} = \frac{MLT^{-2}}{L} = MT^{-2}$

The dimensions of ``m`` and ``A`` are ``M`` and ``L``, respectively.
Returning to (1) we get

$ML^2 T^{-2} = [M]^x [MT^{-2}]^y [L]^z = M^{x + y} L^z T^{-2y}.$

This gives us the following three equations:

$\begin{align*}
x + y &= 1 \\
z &= 2 \\
-2y &= -2
\end{align*}$

Clearly, ``z = 2``, ``y = 1``, and from the first equation ``x = 0``.
Thus, using (1) the energy scale in terms of ``m``, ``k``, and ``A`` is

$E = m^0 k^1 A^2 = kA^2.$

**(b).** The energy scale for quantum mechanical oscillations in terms of ``m``, ``k``, and ``\hbar`` can be written as

$E = m^x k^y \hbar^z \tag{2}$

The dimensions of ``\hbar`` can be found using the formula for angular momentum, ``L = pr``, where the dimensions of momentum ``p`` are given by ``[p] = [mv] = MLT^{-1}`` and the dimensions of length ``r`` are given by ``[r] = L``,

$[\hbar] = [MLT^{-1}][L] = ML^2 T^{-1}$

The dimensions of ``m`` and ``k`` are ``M`` and ``MT^{-2}``, respectively.
Returning to (2) we get

$ML^2 T^{-2} = [M]^x [MT^{-2}]^y [ML^2 T^{-1}]^z = M^{x + y + z} L^{2z} T^{-2y - z}$

This gives us the following three equations:

$\begin{align*}
x + y + z &= 1 \\
2z &= 2 \\
-2y - z &= -2
\end{align*}$

Clearly, ``z = 1`` and from the third equation, ``y = \frac{1}{2}``.
Then from the first equation ``x = -\frac{1}{2}``.
Thus, using (2) the energy scale for quantum mechanical oscillations in terms ``m``, ``k``, and ``\hbar`` is

$E = m^{-\frac{1}{2}} k^{\frac{1}{2}} \hbar^1 = \frac{\hbar \sqrt{k}}{\sqrt{m}}.$
"""

# ╔═╡ b5373d61-8c65-4426-b138-e68ebafdbd88
md"""
### Problem 3

The scale of the Planck Length ``ℓ_P`` in terms of ``G``, ``\hbar``, and ``c`` can be written as

$ℓ_P = G^x \hbar^y c^z \tag{3}$

The dimensions of ``G`` can be found using Newton's law of gravity,

$F = G \frac{m_1 m_2}{r^2} \implies MLT^{-2} = [G] M^2 L^{-2} \implies [G] = M^{-1} L^3 T^{-2}$

The dimensions of ``ℓ_P``, ``\hbar``, and ``c`` are ``L``, ``ML^2 T^{-1}``, and ``LT^{-1}``, respectively.
Returning to (3) we get

$L = [M^{-1} L^3 T^{-2}]^x [ML^2 T^{-1}]^y [LT^{-1}]^z = M^{-x + y} L^{3x + 2y + z} T^{-2x - y - z}$

This gives us the following three equations:

$\begin{align*}
-x + y &= 0 \\
3x + 2y + z &= 1 \\
-2x - y - z &= 0
\end{align*}$

From the first equation, we see that ``x = y``.
Adding the last two equations we get ``x + y = 1 \implies x = y = \frac{1}{2}``.
From the last equation we find ``-1 - \frac{1}{2} - z = 0``, so ``z = -\frac{3}{2}``.
Thus, using (3) the Planck Length scale in terms of ``G``, ``\hbar``, and ``c`` is

$ℓ_P = G^{\frac{1}{2}} \hbar^{\frac{1}{2}} c^{-\frac{3}{2}} = \sqrt{\frac{G \hbar}{c^3}} ≈ 1.616255 × 10^{-35} \text{ m}.$
"""

# ╔═╡ 0fcce5e8-bbab-41fb-81d5-e1f41002df16
# Numerical evaluation of the Planck Length
ℓₚ = √(G * ħ / c_0^3) |> u"m"

# ╔═╡ 3575874e-a020-4d54-a364-70431cc0b771
md"""
Comparing between the Planck Length ``ℓ_P`` and the size of a proton with radius ``R_e`` and diameter ``D_e`` we can write

$ℓ_P ⋅ y = D_e$
"""

# ╔═╡ 6ec966dc-5a75-4b1b-815f-1ae1da637f85
# Radius of a proton
Rₑ = 0.833u"fm" |> u"m"

# ╔═╡ 5d5e81df-2b44-4a7d-96fc-37b5df750094
# Diameter of a proton
Dₑ = 2Rₑ

# ╔═╡ 93f4a5b3-bcb0-44be-8396-4c4bbd07d9ac
Rₑ / ℓₚ

# ╔═╡ edece3e4-4cc4-481b-9469-f2f55900e624
Dₑ / ℓₚ

# ╔═╡ bc9c7397-a6c1-42fb-b0b5-1a262ee3f023
md"""
The Planck Length ``ℓ_P`` is about ``5.1539 × 10^{-19}`` times the radius of a proton ``R_e`` and ``1.0308 × 10^{-20}`` times the diameter of a proton ``D_e``.
"""

# ╔═╡ a53c21c9-af86-4861-8165-fc5e69e1dabf
md"""
### Problem 4

**(a).** Let ``f(x) = x^n`` and ``f'(x) = nx^{n - 1}`` for some positive integer ``n``.
We can illustrate that the relationship holds for ``n = 0`` by considering ``f(x + Δx) = (x + Δx)^0 = 1`` and ``f(x) = x^0 = 1`` for ``n = 0``, so

$f(x + Δx) - f(x) = 1 - 1 = 0$

From the definition of the derivative of a function,

$f'(x) = \lim_{Δx → 0} \frac{f(x + Δx) - f(x)}{Δx} = \lim_{Δx → 0} \frac{(x + Δx)^0 - x^0}{Δx} = \lim_{Δx → 0} \frac{0}{Δx} = 0$

The result of the derivative is equivalent to ``nx^{n - 1}`` where ``nx^{n - 1} = 0x^{0 - 1} = 0`` using ``n = 0``. Thus, the relation also holds for ``n = 0``.

**(b).** Similarly, we can illustrate that the relation holds when ``n`` is a negative integer by considering for ``n = -m`` where ``m > 0`` that

$f(x + Δx) = (x + Δx)^{-m} = \frac{1}{(x + Δx)^m} = \frac{x^m}{x^m (x + Δx)^m}$

and

$f(x) = x^{-m} = \frac{1}{x^m} = \frac{(x + Δx)^m}{x^m (x + Δx)^m}$

so

$\begin{align*}
f(x + Δx) - f(x) &= \frac{x^m - (x + Δx)^m}{x^m (x + Δx)^m} \\
&= \frac{x^m - (x^n + mx^{m - 1} Δx + ⋯)}{x^m (x^n + mx^{m - 1} Δx + ⋯)} \\
&= \frac{-mx^{m - 1} Δx - ⋯}{x^m (x^m + mx^{m - 1} Δx + ⋯)}
\end{align*}$

Using the definition of the derivative,

$f'(x) = \lim_{Δx → 0} \frac{-mx^{n - 1} Δx - ⋯}{x^m (x^m + mx^{m - 1} Δx + ⋯)} \frac{1}{Δx} = \lim_{Δx → 0} \frac{-mx^{m - 1}}{x^{2m}} = -mx^{-m - 1}$

The result of the derivative is equivalent to ``nx^{n - 1}`` where ``nx^{n - 1} = -mx^{-m - 1}`` using ``n = -m``.
Thus, the relation also holds when ``n`` is a negative integer.

**(c).**
We can illustrate that this relation still holds if ``f(x) = x^{p/q}`` where ``p`` and ``q`` are integers and ``q ≠ 0``, i.e., when the exponent is a rational number using the fact that ``f'(x) = nx^{n - 1}`` for ``\{n ∣ n ∈ ℤ ∧ n ≤ 0\}`` as shown from (a) and (b).
Let's consider ``y^q = x^p`` and show that ``y' = \frac{p}{q} x^{\frac{p}{q} - 1}`` for ``y = f(x)``.
First, we need to separate the exponent ``q`` from ``y`` to get ``y`` by itself.
We do so by taking the log of the absolute value of both sides of the equation,

$\begin{align*}
\ln{|y^q|} &= \ln{|x^p|} \\
q \ln{|y|} &= p \ln{|x|} \\
\ln{|y|} &= \frac{p}{q} \ln{|x|} \tag{4}
\end{align*}$

Now, ``y`` is stuck inside of ``\ln``, so to get it out we must differentiate both sides of the equation using ``\frac{d}{dx} (\ln{|y|}) = \frac{1}{y} ⋅ y'`` and ``\frac{d}{dx} (\ln{|x|}) = \frac{1}{x}``,

$\begin{align*}
\frac{1}{y} ⋅ y' &= \frac{p}{q} \frac{1}{x} && x, y ≠ 0 \\
y' &= \frac{p}{q} \frac{y}{x} \tag{5}
\end{align*}$

We have ``y'`` in terms of ``x`` and ``y`` but we don't know what ``y`` is yet.
We can use log rules on equation (4) to find ``y`` in terms of ``x``, ``p``, and ``q``,

$\begin{align*}
\ln{|y|} &= \ln{\left|x^{\frac{p}{q}}\right|} \\
e^{\ln{|y|}} &= e^{\ln{\left|x^{\frac{p}{q}}\right|}} \\
y &= x^{\frac{p}{q}}
\end{align*}$

Going back to equation (5), rewrite ``y'`` in terms of ``x``, ``p``, and ``q``,

$\begin{align*}
y' &= \frac{p}{q} \frac{x^{\frac{p}{q}}}{x} \\
&= \frac{p}{q} x^{\frac{p}{q} - 1}
\end{align*}$

Indeed, the relation holds for ``f(x) = x^{p/q}`` as for ``n = \frac{p}{q}`` we get ``f'(x) = \frac{p}{q} x^{\frac{p}{q} - 1}`` which matches our expectation that ``f'(x) = nx^{n - 1}``.
From (a), the case that ``\frac{p}{q} = 0`` is covered.
From (b), the cases that ``p < 0`` or ``q < 0`` are also covered.

**(d).**
We can illustrate that the relation holds for any ``n ∈ ℝ`` by going through a similar procedure as we did for (c), except this time instead of finding the derivative of ``x^{p/q}``, we simply find the derivative of ``x^n``,

$\begin{align*}
f(x) &= x^n \\
\log{(f(x))} &= n \log{(x)} \\
\frac{d}{dx} [\log{(f(x))}] &= \frac{d}{dx} [n \log{(x)}] \\
\frac{1}{f(x)} ⋅ f'(x) &= \frac{n}{x} \\
f'(x) &= \frac{n f(x)}{x} \\
&= \frac{n x^n}{x} \\
&= nx^{n - 1}
\end{align*}$

In this method, there are no constraints on ``n`` apart from it being a real number.
Indeed, the relation holds for all ``n ∈ ℝ`` as we can see that ``f'(x) = nx^{n - 1}`` for any ``n ∈ ℝ``.
"""

# ╔═╡ 0ded3fa4-d4e1-4304-af36-7b575c4309f8
md"""
### Problem 5
"""

# ╔═╡ 4859431c-498e-4cea-ace7-d572624b6f11
md"""
The velocity in the ``x`` and ``y`` directions of the particle is given by

$v_x = \frac{dx}{dt} = \frac{d}{dt}(x)$

and

$v_y = \frac{dy}{dt} = \frac{d}{dt}(y),$

respectively.
To find the velocities in terms of the position coordinates ``x`` and ``y``, we consider that the ``x`` and ``y`` positions of the particle over time ``t`` is defined by the following parametric equations,

$\begin{align*}
x(t) &= \cos{t} \\
y(t) &= \sin{t}
\end{align*}$

Then we can rewrite the ``x`` and ``y`` velocities in terms of time ``t`` as follows,

$\begin{align*}
v_x &= \frac{d}{dt} (\cos{t}) = -\sin{t} \\
v_y &= \frac{d}{dt} (\sin{t}) = \cos{t}
\end{align*}$
"""

# ╔═╡ 8583789c-551c-4d05-8a1a-2a8f671a431a
let
	figurepath = "img/velocity_circular_motion.png"
	load(figurepath)
end

# ╔═╡ 0d8be6b5-d832-465f-969b-969eaf2d07cd
md"""
The drawing agrees with my answer.
The point at ``t = 0`` gives us the position ``(\cos{0}, \sin{0}) = (1, 0)`` and the corresponding velocity is given by ``\langle -\sin{0}, \cos{0} \rangle = \langle 0, 1 \rangle``.
The point at ``t = \frac{\pi}{2}`` gives us the position ``(\cos{\frac{\pi}{2}}, \sin{\frac{\pi}{2}}) = (0, 1)`` and the corresponding velocity is given by ``\langle -\sin{\frac{\pi}{2}}, \cos{\frac{\pi}{2}} \rangle = \langle -1, 0 \rangle``.
The point at ``t = \pi`` gives us the position ``(\cos{\pi}, \sin{\pi}) = (-1, 0)`` and the corresponding velocity is given by ``\langle -\sin{\pi}, \cos{\pi} \rangle = \langle 0, 1 \rangle``.
The point at ``t = \frac{3\pi}{2}`` gives us the position ``(\cos{\frac{3\pi}{2}}, \sin{\frac{3\pi}{2}}) = (0, -1)`` and the corresponding velocity is given by ``\langle -\sin{\frac{3\pi}{2}}, \cos{\frac{3\pi}{2}} \rangle = \langle 1, 0 \rangle``.
All of the positions and velocities for each ``t`` match accordingly with the drawing.
"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
PhysicalConstants = "5ad8b20f-a522-5ce9-bfc9-ddf1d5bda6ab"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[compat]
Images = "~0.25.1"
PhysicalConstants = "~0.2.1"
Unitful = "~1.10.1"
"""

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

julia_version = "1.7.1"
manifest_format = "2.0"

[[deps.AbstractFFTs]]
deps = ["ChainRulesCore", "LinearAlgebra"]
git-tree-sha1 = "6f1d9bc1c08f9f4a8fa92e3ea3cb50153a1b40d4"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.1.0"

[[deps.Adapt]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "af92965fb30777147966f58acb05da51c5616b5f"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.3.3"

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

[[deps.ArnoldiMethod]]
deps = ["LinearAlgebra", "Random", "StaticArrays"]
git-tree-sha1 = "62e51b39331de8911e4a7ff6f5aaf38a5f4cc0ae"
uuid = "ec485272-7323-5ecc-a04f-4719b315124d"
version = "0.2.0"

[[deps.ArrayInterface]]
deps = ["Compat", "IfElse", "LinearAlgebra", "Requires", "SparseArrays", "Static"]
git-tree-sha1 = "ffc6588e17bcfcaa79dfa5b4f417025e755f83fc"
uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
version = "4.0.1"

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

[[deps.AxisAlgorithms]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"]
git-tree-sha1 = "66771c8d21c8ff5e3a93379480a2307ac36863f7"
uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950"
version = "1.0.1"

[[deps.AxisArrays]]
deps = ["Dates", "IntervalSets", "IterTools", "RangeArrays"]
git-tree-sha1 = "d127d5e4d86c7680b20c35d40b503c74b9a39b5e"
uuid = "39de3d68-74b9-583c-8d2d-e117c070f3a9"
version = "0.4.4"

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

[[deps.CEnum]]
git-tree-sha1 = "215a9aa4a1f23fbd05b92769fdd62559488d70e9"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.4.1"

[[deps.Calculus]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
version = "0.5.1"

[[deps.CatIndices]]
deps = ["CustomUnitRanges", "OffsetArrays"]
git-tree-sha1 = "a0f80a09780eed9b1d106a1bf62041c2efc995bc"
uuid = "aafaddc9-749c-510e-ac4f-586e18779b91"
version = "0.2.2"

[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "926870acb6cbcf029396f2f2de030282b6bc1941"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.11.4"

[[deps.ChangesOfVariables]]
deps = ["ChainRulesCore", "LinearAlgebra", "Test"]
git-tree-sha1 = "bf98fa45a0a4cee295de98d4c1462be26345b9a1"
uuid = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
version = "0.1.2"

[[deps.Clustering]]
deps = ["Distances", "LinearAlgebra", "NearestNeighbors", "Printf", "SparseArrays", "Statistics", "StatsBase"]
git-tree-sha1 = "75479b7df4167267d75294d14b58244695beb2ac"
uuid = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5"
version = "0.14.2"

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

[[deps.ColorVectorSpace]]
deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "SpecialFunctions", "Statistics", "TensorCore"]
git-tree-sha1 = "3f1f500312161f1ae067abe07d13b40f78f32e07"
uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4"
version = "0.9.8"

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

[[deps.CommonSolve]]
git-tree-sha1 = "68a0743f578349ada8bc911a5cbd5a2ef6ed6d1f"
uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
version = "0.2.0"

[[deps.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 = "44c37b4636bc54afac5c574d2d02b625349d6582"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "3.41.0"

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

[[deps.ComputationalResources]]
git-tree-sha1 = "52cb3ec90e8a8bea0e62e275ba577ad0f74821f7"
uuid = "ed09eef8-17a6-5b46-8889-db040fac31e3"
version = "0.3.2"

[[deps.ConstructionBase]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f74e9d5388b8620b4cee35d4c5a618dd4dc547f4"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.3.0"

[[deps.CoordinateTransformations]]
deps = ["LinearAlgebra", "StaticArrays"]
git-tree-sha1 = "681ea870b918e7cff7111da58791d7f718067a19"
uuid = "150eb455-5306-5404-9cee-2592286d6298"
version = "0.6.2"

[[deps.CustomUnitRanges]]
git-tree-sha1 = "1a3f97f907e6dd8983b744d2642651bb162a3f7a"
uuid = "dc8bdbbb-1ca9-579f-8c36-e416f6a65cce"
version = "1.0.2"

[[deps.DataAPI]]
git-tree-sha1 = "cc70b17275652eb47bc9e5f81635981f13cea5c8"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.9.0"

[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "3daef5523dd2e769dad2365274f760ff5f282c7d"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.11"

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

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

[[deps.Distances]]
deps = ["LinearAlgebra", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "3258d0659f812acde79e8a74b11f17ac06d0ca04"
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
version = "0.10.7"

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

[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "b19534d1895d702889b219c382a6e18010797f0b"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.8.6"

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

[[deps.DualNumbers]]
deps = ["Calculus", "NaNMath", "SpecialFunctions"]
git-tree-sha1 = "84f04fe68a3176a583b864e492578b9466d87f1e"
uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
version = "0.6.6"

[[deps.EllipsisNotation]]
deps = ["ArrayInterface"]
git-tree-sha1 = "d7ab55febfd0907b285fbf8dc0c73c0825d9d6aa"
uuid = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
version = "1.3.0"

[[deps.FFTViews]]
deps = ["CustomUnitRanges", "FFTW"]
git-tree-sha1 = "cbdf14d1e8c7c8aacbe8b19862e0179fd08321c2"
uuid = "4f61f5a4-77b1-5117-aa51-3ab5ef4ef0cd"
version = "0.3.2"

[[deps.FFTW]]
deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"]
git-tree-sha1 = "463cb335fa22c4ebacfd1faba5fde14edb80d96c"
uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
version = "1.4.5"

[[deps.FFTW_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "c6033cc3892d0ef5bb9cd29b7f2f0331ea5184ea"
uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a"
version = "3.3.10+0"

[[deps.FileIO]]
deps = ["Pkg", "Requires", "UUIDs"]
git-tree-sha1 = "67551df041955cc6ee2ed098718c8fcd7fc7aebe"
uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
version = "1.12.0"

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

[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"

[[deps.Ghostscript_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "78e2c69783c9753a91cdae88a8d432be85a2ab5e"
uuid = "61579ee1-b43e-5ca0-a5da-69d92c66a64b"
version = "9.55.0+0"

[[deps.Graphics]]
deps = ["Colors", "LinearAlgebra", "NaNMath"]
git-tree-sha1 = "1c5a84319923bea76fa145d49e93aa4394c73fc2"
uuid = "a2bd30eb-e257-5431-a919-1863eab51364"
version = "1.1.1"

[[deps.Graphs]]
deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"]
git-tree-sha1 = "d727758173afef0af878b29ac364a0eca299fc6b"
uuid = "86223c79-3864-5bf0-83f7-82e725a168b6"
version = "1.5.1"

[[deps.IfElse]]
git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1"
uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
version = "0.1.1"

[[deps.ImageAxes]]
deps = ["AxisArrays", "ImageBase", "ImageCore", "Reexport", "SimpleTraits"]
git-tree-sha1 = "c54b581a83008dc7f292e205f4c409ab5caa0f04"
uuid = "2803e5a7-5153-5ecf-9a86-9b4c37f5f5ac"
version = "0.6.10"

[[deps.ImageBase]]
deps = ["ImageCore", "Reexport"]
git-tree-sha1 = "b51bb8cae22c66d0f6357e3bcb6363145ef20835"
uuid = "c817782e-172a-44cc-b673-b171935fbb9e"
version = "0.1.5"

[[deps.ImageContrastAdjustment]]
deps = ["ImageCore", "ImageTransformations", "Parameters"]
git-tree-sha1 = "0d75cafa80cf22026cea21a8e6cf965295003edc"
uuid = "f332f351-ec65-5f6a-b3d1-319c6670881a"
version = "0.3.10"

[[deps.ImageCore]]
deps = ["AbstractFFTs", "ColorVectorSpace", "Colors", "FixedPointNumbers", "Graphics", "MappedArrays", "MosaicViews", "OffsetArrays", "PaddedViews", "Reexport"]
git-tree-sha1 = "9a5c62f231e5bba35695a20988fc7cd6de7eeb5a"
uuid = "a09fc81d-aa75-5fe9-8630-4744c3626534"
version = "0.9.3"

[[deps.ImageDistances]]
deps = ["Distances", "ImageCore", "ImageMorphology", "LinearAlgebra", "Statistics"]
git-tree-sha1 = "7a20463713d239a19cbad3f6991e404aca876bda"
uuid = "51556ac3-7006-55f5-8cb3-34580c88182d"
version = "0.2.15"

[[deps.ImageFiltering]]
deps = ["CatIndices", "ComputationalResources", "DataStructures", "FFTViews", "FFTW", "ImageBase", "ImageCore", "LinearAlgebra", "OffsetArrays", "Reexport", "SparseArrays", "StaticArrays", "Statistics", "TiledIteration"]
git-tree-sha1 = "15bd05c1c0d5dbb32a9a3d7e0ad2d50dd6167189"
uuid = "6a3955dd-da59-5b1f-98d4-e7296123deb5"
version = "0.7.1"

[[deps.ImageIO]]
deps = ["FileIO", "Netpbm", "OpenEXR", "PNGFiles", "QOI", "Sixel", "TiffImages", "UUIDs"]
git-tree-sha1 = "816fc866edd8307a6e79a575e6585bfab8cef27f"
uuid = "82e4d734-157c-48bb-816b-45c225c6df19"
version = "0.6.0"

[[deps.ImageMagick]]
deps = ["FileIO", "ImageCore", "ImageMagick_jll", "InteractiveUtils", "Libdl", "Pkg", "Random"]
git-tree-sha1 = "5bc1cb62e0c5f1005868358db0692c994c3a13c6"
uuid = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
version = "1.2.1"

[[deps.ImageMagick_jll]]
deps = ["Artifacts", "Ghostscript_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pkg", "Zlib_jll", "libpng_jll"]
git-tree-sha1 = "f025b79883f361fa1bd80ad132773161d231fd9f"
uuid = "c73af94c-d91f-53ed-93a7-00f77d67a9d7"
version = "6.9.12+2"

[[deps.ImageMetadata]]
deps = ["AxisArrays", "ImageAxes", "ImageBase", "ImageCore"]
git-tree-sha1 = "36cbaebed194b292590cba2593da27b34763804a"
uuid = "bc367c6b-8a6b-528e-b4bd-a4b897500b49"
version = "0.9.8"

[[deps.ImageMorphology]]
deps = ["ImageCore", "LinearAlgebra", "Requires", "TiledIteration"]
git-tree-sha1 = "5581e18a74a5838bd919294a7138c2663d065238"
uuid = "787d08f9-d448-5407-9aad-5290dd7ab264"
version = "0.3.0"

[[deps.ImageQualityIndexes]]
deps = ["ImageContrastAdjustment", "ImageCore", "ImageDistances", "ImageFiltering", "OffsetArrays", "Statistics"]
git-tree-sha1 = "1d2d73b14198d10f7f12bf7f8481fd4b3ff5cd61"
uuid = "2996bd0c-7a13-11e9-2da2-2f5ce47296a9"
version = "0.3.0"

[[deps.ImageSegmentation]]
deps = ["Clustering", "DataStructures", "Distances", "Graphs", "ImageCore", "ImageFiltering", "ImageMorphology", "LinearAlgebra", "MetaGraphs", "RegionTrees", "SimpleWeightedGraphs", "StaticArrays", "Statistics"]
git-tree-sha1 = "36832067ea220818d105d718527d6ed02385bf22"
uuid = "80713f31-8817-5129-9cf8-209ff8fb23e1"
version = "1.7.0"

[[deps.ImageShow]]
deps = ["Base64", "FileIO", "ImageBase", "ImageCore", "OffsetArrays", "StackViews"]
git-tree-sha1 = "d0ac64c9bee0aed6fdbb2bc0e5dfa9a3a78e3acc"
uuid = "4e3cecfd-b093-5904-9786-8bbb286a6a31"
version = "0.3.3"

[[deps.ImageTransformations]]
deps = ["AxisAlgorithms", "ColorVectorSpace", "CoordinateTransformations", "ImageBase", "ImageCore", "Interpolations", "OffsetArrays", "Rotations", "StaticArrays"]
git-tree-sha1 = "b4b161abc8252d68b13c5cc4a5f2ba711b61fec5"
uuid = "02fcd773-0e25-5acc-982a-7f6622650795"
version = "0.9.3"

[[deps.Images]]
deps = ["Base64", "FileIO", "Graphics", "ImageAxes", "ImageBase", "ImageContrastAdjustment", "ImageCore", "ImageDistances", "ImageFiltering", "ImageIO", "ImageMagick", "ImageMetadata", "ImageMorphology", "ImageQualityIndexes", "ImageSegmentation", "ImageShow", "ImageTransformations", "IndirectArrays", "IntegralArrays", "Random", "Reexport", "SparseArrays", "StaticArrays", "Statistics", "StatsBase", "TiledIteration"]
git-tree-sha1 = "11d268adba1869067620659e7cdf07f5e54b6c76"
uuid = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
version = "0.25.1"

[[deps.Imath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "87f7662e03a649cffa2e05bf19c303e168732d3e"
uuid = "905a6f67-0a94-5f89-b386-d35d92009cd1"
version = "3.1.2+0"

[[deps.IndirectArrays]]
git-tree-sha1 = "012e604e1c7458645cb8b436f8fba789a51b257f"
uuid = "9b13fd28-a010-5f03-acff-a1bbcff69959"
version = "1.0.0"

[[deps.Inflate]]
git-tree-sha1 = "f5fc07d4e706b84f72d54eedcc1c13d92fb0871c"
uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
version = "0.1.2"

[[deps.IntegralArrays]]
deps = ["ColorTypes", "FixedPointNumbers", "IntervalSets"]
git-tree-sha1 = "00019244715621f473d399e4e1842e479a69a42e"
uuid = "1d092043-8f09-5a30-832f-7509e371ab51"
version = "0.1.2"

[[deps.IntelOpenMP_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "d979e54b71da82f3a65b62553da4fc3d18c9004c"
uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0"
version = "2018.0.3+2"

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

[[deps.Interpolations]]
deps = ["AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "Requires", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"]
git-tree-sha1 = "b15fc0a95c564ca2e0a7ae12c1f095ca848ceb31"
uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59"
version = "0.13.5"

[[deps.IntervalSets]]
deps = ["Dates", "EllipsisNotation", "Statistics"]
git-tree-sha1 = "3cc368af3f110a767ac786560045dceddfc16758"
uuid = "8197267c-284f-5f27-9208-e0e47529a953"
version = "0.5.3"

[[deps.InverseFunctions]]
deps = ["Test"]
git-tree-sha1 = "a7254c0acd8e62f1ac75ad24d5db43f5f19f3c65"
uuid = "3587e190-3f89-42d0-90ee-14403ec27112"
version = "0.1.2"

[[deps.IrrationalConstants]]
git-tree-sha1 = "7fd44fd4ff43fc60815f8e764c0f352b83c49151"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.1.1"

[[deps.IterTools]]
git-tree-sha1 = "fa6287a4469f5e048d763df38279ee729fbd44e5"
uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
version = "1.4.0"

[[deps.JLD2]]
deps = ["DataStructures", "FileIO", "MacroTools", "Mmap", "Pkg", "Printf", "Reexport", "TranscodingStreams", "UUIDs"]
git-tree-sha1 = "09ef0c32a26f80b465d808a1ba1e85775a282c97"
uuid = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
version = "0.4.17"

[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "22df5b96feef82434b07327e2d3c770a9b21e023"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.0"

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

[[deps.LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"

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

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

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

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

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

[[deps.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"

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

[[deps.LogExpFunctions]]
deps = ["ChainRulesCore", "ChangesOfVariables", "DocStringExtensions", "InverseFunctions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "e5718a00af0ab9756305a0392832c8952c7426c1"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.6"

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

[[deps.MKL_jll]]
deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "5455aef09b40e5020e1520f551fa3135040d4ed0"
uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7"
version = "2021.1.1+2"

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

[[deps.MappedArrays]]
git-tree-sha1 = "e8b359ef06ec72e8c030463fe02efe5527ee5142"
uuid = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
version = "0.4.1"

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

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

[[deps.Measurements]]
deps = ["Calculus", "LinearAlgebra", "Printf", "RecipesBase", "Requires"]
git-tree-sha1 = "58390f5617544fb09d27244749484fee0cae6712"
uuid = "eff96d63-e80a-5855-80a2-b1b0885c5ab7"
version = "2.7.0"

[[deps.MetaGraphs]]
deps = ["Graphs", "JLD2", "Random"]
git-tree-sha1 = "2af69ff3c024d13bde52b34a2a7d6887d4e7b438"
uuid = "626554b9-1ddb-594c-aa3c-2596fe9399a5"
version = "0.7.1"

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

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

[[deps.MosaicViews]]
deps = ["MappedArrays", "OffsetArrays", "PaddedViews", "StackViews"]
git-tree-sha1 = "b34e3bc3ca7c94914418637cb10cc4d1d80d877d"
uuid = "e94cdb99-869f-56ef-bcf0-1ae2bcbe0389"
version = "0.3.3"

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

[[deps.NaNMath]]
git-tree-sha1 = "f755f36b19a5116bb580de457cda0c140153f283"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "0.3.6"

[[deps.NearestNeighbors]]
deps = ["Distances", "StaticArrays"]
git-tree-sha1 = "16baacfdc8758bc374882566c9187e785e85c2f0"
uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce"
version = "0.4.9"

[[deps.Netpbm]]
deps = ["FileIO", "ImageCore"]
git-tree-sha1 = "18efc06f6ec36a8b801b23f076e3c6ac7c3bf153"
uuid = "f09324ee-3d7c-5217-9330-fc30815ba969"
version = "1.0.2"

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

[[deps.OffsetArrays]]
deps = ["Adapt"]
git-tree-sha1 = "043017e0bdeff61cfbb7afeb558ab29536bbb5ed"
uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"
version = "1.10.8"

[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"

[[deps.OpenEXR]]
deps = ["Colors", "FileIO", "OpenEXR_jll"]
git-tree-sha1 = "327f53360fdb54df7ecd01e96ef1983536d1e633"
uuid = "52e1d378-f018-4a11-a4be-720524705ac7"
version = "0.3.2"

[[deps.OpenEXR_jll]]
deps = ["Artifacts", "Imath_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"]
git-tree-sha1 = "923319661e9a22712f24596ce81c54fc0366f304"
uuid = "18a262bb-aa17-5467-a713-aee519bc75cb"
version = "3.1.1+0"

[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"

[[deps.OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"

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

[[deps.PNGFiles]]
deps = ["Base64", "CEnum", "ImageCore", "IndirectArrays", "OffsetArrays", "libpng_jll"]
git-tree-sha1 = "6d105d40e30b635cfed9d52ec29cf456e27d38f8"
uuid = "f57f5aa1-a3ce-4bc8-8ab9-96f992907883"
version = "0.3.12"

[[deps.PaddedViews]]
deps = ["OffsetArrays"]
git-tree-sha1 = "03a7a85b76381a3d04c7a1656039197e70eda03d"
uuid = "5432bcbf-9aad-5242-b902-cca2824c8663"
version = "0.5.11"

[[deps.Parameters]]
deps = ["OrderedCollections", "UnPack"]
git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe"
uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a"
version = "0.12.3"

[[deps.PhysicalConstants]]
deps = ["Measurements", "Roots", "Unitful"]
git-tree-sha1 = "2bc26b693b5cbc823c54b33ea88a9209d27e2db7"
uuid = "5ad8b20f-a522-5ce9-bfc9-ddf1d5bda6ab"
version = "0.2.1"

[[deps.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"

[[deps.PkgVersion]]
deps = ["Pkg"]
git-tree-sha1 = "a7a7e1a88853564e551e4eba8650f8c38df79b37"
uuid = "eebad327-c553-4316-9ea0-9fa01ccd7688"
version = "0.1.1"

[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "2cf929d64681236a2e074ffafb8d568733d2e6af"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.2.3"

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

[[deps.ProgressMeter]]
deps = ["Distributed", "Printf"]
git-tree-sha1 = "afadeba63d90ff223a6a48d2009434ecee2ec9e8"
uuid = "92933f4c-e287-5a05-a399-4b506db050ca"
version = "1.7.1"

[[deps.QOI]]
deps = ["ColorTypes", "FileIO", "FixedPointNumbers"]
git-tree-sha1 = "18e8f4d1426e965c7b532ddd260599e1510d26ce"
uuid = "4b34888f-f399-49d4-9bb3-47ed5cae4e65"
version = "1.0.0"

[[deps.Quaternions]]
deps = ["DualNumbers", "LinearAlgebra"]
git-tree-sha1 = "adf644ef95a5e26c8774890a509a55b7791a139f"
uuid = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0"
version = "0.4.2"

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

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

[[deps.RangeArrays]]
git-tree-sha1 = "b9039e93773ddcfc828f12aadf7115b4b4d225f5"
uuid = "b3c3ace0-ae52-54e7-9d0b-2c1406fd6b9d"
version = "0.3.2"

[[deps.Ratios]]
deps = ["Requires"]
git-tree-sha1 = "01d341f502250e81f6fec0afe662aa861392a3aa"
uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439"
version = "0.4.2"

[[deps.RecipesBase]]
git-tree-sha1 = "6bf3f380ff52ce0832ddd3a2a7b9538ed1bcca7d"
uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
version = "1.2.1"

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

[[deps.RegionTrees]]
deps = ["IterTools", "LinearAlgebra", "StaticArrays"]
git-tree-sha1 = "4618ed0da7a251c7f92e869ae1a19c74a7d2a7f9"
uuid = "dee08c22-ab7f-5625-9660-a9af2021b33f"
version = "0.3.2"

[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"

[[deps.Roots]]
deps = ["CommonSolve", "Printf", "Setfield"]
git-tree-sha1 = "0abe7fc220977da88ad86d339335a4517944fea2"
uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665"
version = "1.3.14"

[[deps.Rotations]]
deps = ["LinearAlgebra", "Quaternions", "Random", "StaticArrays", "Statistics"]
git-tree-sha1 = "2fa87d198bc5356c649b92109ed3ce46ee1eb89d"
uuid = "6038ab10-8711-5258-84ad-4b1120ba62dc"
version = "1.1.1"

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

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

[[deps.Setfield]]
deps = ["ConstructionBase", "Future", "MacroTools", "Requires"]
git-tree-sha1 = "0afd9e6c623e379f593da01f20590bacc26d1d14"
uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
version = "0.8.1"

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

[[deps.SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.4"

[[deps.SimpleWeightedGraphs]]
deps = ["Graphs", "LinearAlgebra", "Markdown", "SparseArrays", "Test"]
git-tree-sha1 = "a6f404cc44d3d3b28c793ec0eb59af709d827e4e"
uuid = "47aef6b3-ad0c-573a-a1e2-d07658019622"
version = "1.2.1"

[[deps.Sixel]]
deps = ["Dates", "FileIO", "ImageCore", "IndirectArrays", "OffsetArrays", "REPL", "libsixel_jll"]
git-tree-sha1 = "8fb59825be681d451c246a795117f317ecbcaa28"
uuid = "45858cf5-a6b0-47a3-bbea-62219f50df47"
version = "0.1.2"

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

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

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

[[deps.SpecialFunctions]]
deps = ["ChainRulesCore", "IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "e08890d19787ec25029113e88c34ec20cac1c91e"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.0.0"

[[deps.StackViews]]
deps = ["OffsetArrays"]
git-tree-sha1 = "46e589465204cd0c08b4bd97385e4fa79a0c770c"
uuid = "cae243ae-269e-4f55-b966-ac2d0dc13c15"
version = "0.1.1"

[[deps.Static]]
deps = ["IfElse"]
git-tree-sha1 = "b4912cd034cdf968e06ca5f943bb54b17b97793a"
uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3"
version = "0.5.1"

[[deps.StaticArrays]]
deps = ["LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "2ae4fe21e97cd13efd857462c1869b73c9f61be3"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.3.2"

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

[[deps.StatsAPI]]
git-tree-sha1 = "d88665adc9bcf45903013af0982e2fd05ae3d0a6"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.2.0"

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

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

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

[[deps.TensorCore]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6"
uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50"
version = "0.1.1"

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

[[deps.TiffImages]]
deps = ["ColorTypes", "DataStructures", "DocStringExtensions", "FileIO", "FixedPointNumbers", "IndirectArrays", "Inflate", "OffsetArrays", "PkgVersion", "ProgressMeter", "UUIDs"]
git-tree-sha1 = "991d34bbff0d9125d93ba15887d6594e8e84b305"
uuid = "731e570b-9d59-4bfa-96dc-6df516fadf69"
version = "0.5.3"

[[deps.TiledIteration]]
deps = ["OffsetArrays"]
git-tree-sha1 = "5683455224ba92ef59db72d10690690f4a8dc297"
uuid = "06e1c1a7-607b-532d-9fad-de7d9aa2abac"
version = "0.3.1"

[[deps.TranscodingStreams]]
deps = ["Random", "Test"]
git-tree-sha1 = "216b95ea110b5972db65aa90f88d8d89dcb8851c"
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
version = "0.9.6"

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

[[deps.UnPack]]
git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b"
uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
version = "1.0.2"

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

[[deps.Unitful]]
deps = ["ConstructionBase", "Dates", "LinearAlgebra", "Random"]
git-tree-sha1 = "b95e0b8a8d1b6a6c3e0b3ca393a7a285af47c264"
uuid = "1986cc42-f94f-5a68-af5c-568840ba703d"
version = "1.10.1"

[[deps.WoodburyMatrices]]
deps = ["LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "de67fa59e33ad156a590055375a30b23c40299d3"
uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6"
version = "0.5.5"

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

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

[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl", "OpenBLAS_jll"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"

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

[[deps.libsixel_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "78736dab31ae7a53540a6b752efc61f77b304c5b"
uuid = "075b6546-f08a-558a-be8f-8157d0f608a5"
version = "1.8.6+1"

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

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

# ╔═╡ Cell order:
# ╠═4ab649c8-743f-11ec-181b-f3e7e7ea7e82
# ╟─d72e1ae3-6c5b-49a5-b45a-e8fe2c2f1f67
# ╟─1ba01821-dfb6-44b5-80f2-a131e01b9e8b
# ╟─b5373d61-8c65-4426-b138-e68ebafdbd88
# ╠═0fcce5e8-bbab-41fb-81d5-e1f41002df16
# ╟─3575874e-a020-4d54-a364-70431cc0b771
# ╠═6ec966dc-5a75-4b1b-815f-1ae1da637f85
# ╠═5d5e81df-2b44-4a7d-96fc-37b5df750094
# ╠═93f4a5b3-bcb0-44be-8396-4c4bbd07d9ac
# ╠═edece3e4-4cc4-481b-9469-f2f55900e624
# ╟─bc9c7397-a6c1-42fb-b0b5-1a262ee3f023
# ╟─a53c21c9-af86-4861-8165-fc5e69e1dabf
# ╟─0ded3fa4-d4e1-4304-af36-7b575c4309f8
# ╟─4859431c-498e-4cea-ace7-d572624b6f11
# ╟─8583789c-551c-4d05-8a1a-2a8f671a431a
# ╟─0d8be6b5-d832-465f-969b-969eaf2d07cd
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
module CommunalHelper

using ..Ahorn

function renderCustomDreamBlock(ctx::Ahorn.Cairo.CairoContext, x::Number, y::Number, width::Number, height::Number, featherMode::Bool, oneUse::Bool)
    Ahorn.Cairo.save(ctx)

    Ahorn.set_antialias(ctx, 1)
    Ahorn.set_line_width(ctx, 1)

    fillColor = featherMode ? (0.31, 0.69, 1.0, 0.4) : (0.0, 0.0, 0.0, 0.4)
	 lineColor = oneUse ? (1.0, 0.0, 0.0, 1.0) : (1.0, 1.0, 1.0, 1.0)
    Ahorn.drawRectangle(ctx, x, y, width, height, fillColor, lineColor)

    Ahorn.restore(ctx)
end

end

ext: jl

max_stars_repo_name: FlynnSC/CommunalHelper

max_issues_repo_name: FlynnSC/CommunalHelper

max_forks_repo_name: FlynnSC/CommunalHelper


text:
using Documenter, ColorSchemes, ColorSchemeTools, Luxor, Colors

makedocs(
    modules = [ColorSchemeTools],
    sitename = "ColorSchemeTools",
    format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"),
    pages    = Any[
    "Introduction"             => "index.md",
    "Tools"                    => "tools.md",
    "Converting image colors"  => "convertingimages.md",
    "Making colorschemes"      => "makingschemes.md",
    "Saving colorschemes"      => "output.md",
    "Index"                    => "functionindex.md"
    ]
    )

deploydocs(
    repo = "github.com/JuliaGraphics/ColorSchemeTools.jl.git",
    target = "build"
    )


text:
module Pagerank
export Rank
export stationary_distribution
export readadj, fastadj

include("io.jl")
include("rank.jl")
end


text:
module KnetLayers

using Knet
using UnicodePlots
using Random
using Distributed

import Base.+, Base.*, Base.==

export NeuralNet, NullLayer, LinearLayer, NonlinearLayer, PoolLayer, ConvLayer
export DropoutLayer, BatchnormLayer, ActivationLayer, BiasLayer, DeconvLayer
export Layer, Dense, Pool, Conv1D, Conv2D, Conv3D, Bias, Conv, Deconv
export ReLU, Sigm, Tanh, Dropout, Batchnorm
export operator, weights, repflow, randlayer, depth, train
export isvalid, outdims, flops, nparams, dimflow

#
# LAYER DEFINITIONS AND CONVENIENCES
#

abstract type Layer end
abstract type NullLayer <: Layer end
abstract type ReductionLayer <: Layer end

# TODO: Just const NeuralNet = Array{Layer}  ?
# no, in future want other topologies than just linear, so will need to
# implement trees or graph to hold Layer objects at vertices
mutable struct NeuralNet  # TODO: make some of these types immutable?
    #indims::NTuple{4,Int}
    layers::Array{Layer}
end
NeuralNet() = NeuralNet(Layer[LinearLayer(1)])

depth(N::NeuralNet) = length(N.layers)

#
# Fully Connected (Linear) Layers
#
mutable struct LinearLayer <: Layer
    size::Int
end
# mat(x) = reshape(x, (X1*X2*...*X[D-1],XD))
operator(L::LinearLayer) = (x, w, b) -> w*mat(x) .+ b   # Fully connected layer
nparams(L::LinearLayer) = 2
nparams(L::LinearLayer, indims) =  L.size * prod(indims[1:end-1])
string(L::LinearLayer) = "Dense($(L.size))"
outdims(L::LinearLayer, indims) = (L.size, indims[end])
weights(L::LinearLayer, indims) = (xavier(L.size, prod(indims[1:end-1])),zeros(L.size))
flops(L::LinearLayer, indims) = prod(indims[1:end-1]).^2*L.size + L.size
==(a::LinearLayer, b::LinearLayer) = a.size == b.size
const Linear = LinearLayer
const Dense = LinearLayer

#
#  Nonlinear (Activation) Layers
#
mutable struct NonlinearLayer <: Layer
    op::Function
end
NonlinearOpList = Any[relu, sigm, tanh]
NonlinearOpNames = Dict{Function,String}(relu=>"ReLU",sigm=>"Sigm",tanh=>"Tanh")
ReLU() = NonlinearLayer(relu)
Sigm() = NonlinearLayer(sigm)
Tanh() = NonlinearLayer(tanh)
function leaky_relu(x, alpha=0.2)
    pos = max(0,x)
    neg = min(0,x) * alpha
    return pos + neg
end
LeakyReLU() = NonlinearLayer(leaky_relu)  # TODO
operator(L::NonlinearLayer) = (x) -> (L.op).(x)
nparams(L::NonlinearLayer) = 0
nparams(L::NonlinearLayer, indims) = 0
string(L::NonlinearLayer) = NonlinearOpNames[L.op]*"()"
outdims(L::NonlinearLayer, indims) = indims
weights(L::NonlinearLayer, indims) = ()
flops(L::NonlinearLayer, indims)  = prod(indims)
==(a::NonlinearLayer, b::NonlinearLayer) = a.op == b.op
const ActivationLayer = NonlinearLayer

#
# Convolution Layers
#
mutable struct ConvLayer <: ReductionLayer
    window::Tuple{Int,Int}
    outchan::Int
    stride::Int
    padding::Int
end
ConvLayer(window::Tuple{Int,Int}, outchan) =
    ConvLayer(window::Tuple{Int,Int}, outchan, 1, 0)  # default: stride=1, padding=0
ConvLayer(w::Int, outchan) = ConvLayer((w,w), outchan)
ConvLayer(w::Int, outchan, stride, padding) = ConvLayer((w,w), outchan, stride, padding)
operator(L::ConvLayer) = (x, w, b)-> conv4(w, x, padding=L.padding, stride=L.stride) .+ b
nparams(L::ConvLayer) = 2   # TODO: rename this to nweights?
nparams(L::ConvLayer, indims) = prod(L.window)* indims[3] * L.outchan
string(L::ConvLayer) = "Conv$(length(L.window))D($(L.window), $(L.outchan), $(L.stride), $(L.padding))"
function outdims(L::ConvLayer, X)
    Y1 = 1 + floor(Int, (X[1] + 2*L.padding - L.window[1]) / L.stride)
    Y2 = 1 + floor(Int, (X[2] + 2*L.padding - L.window[2]) / L.stride)
    O = L.outchan
    N = X[3]
    (Y1, Y2, O, N)
end
weights(L::ConvLayer, indims) = (xavier(L.window[1], L.window[2], indims[3], L.outchan),zeros(1,1,L.outchan,1)) # TODO: remove trailing singleton in bias weights?
function flops(L::ConvLayer, indims)
    mw = prod(L.window)
    mw = mw + mw - 1
    return prod(indims[1:2])*mw*L.outchan
end
==(a::ConvLayer, b::ConvLayer) = (a.window==b.window) && (a.outchan==b.outchan) && (a.stride==b.stride) && (a.padding==b.padding)
const Conv = ConvLayer
const Conv1D = ConvLayer
const Conv2D = ConvLayer
const Conv3D = ConvLayer

#
#  Pooling Layers
#
mutable struct PoolLayer <: ReductionLayer
    window::Int
    padding::Int
    stride::Int
    mode::Int
end
PoolLayer() = PoolLayer(2, 0, 2, 0)
operator(L::PoolLayer) = (x) -> pool(x, window=L.window, padding=L.padding, stride=L.stride, mode=L.mode)
nparams(L::PoolLayer) = 0
nparams(L::PoolLayer, indims) = 0
string(L::PoolLayer) = "Pool($(L.window), $(L.padding), $(L.stride), $(L.mode))"
function outdims(L::PoolLayer, X)
    Y1 = 1 + floor(Int, (X[1] + 2*L.padding - L.window) / L.stride)
    Y2 = 1 + floor(Int, (X[2] + 2*L.padding - L.window) / L.stride)
    (Y1, Y2, X[3], X[4])
end
weights(L::PoolLayer, indims) = ()
flops(L::PoolLayer, indims) = prod(indims) # TODO
==(a::PoolLayer, b::PoolLayer) = (a.window==b.window) && (a.mode==b.mode) && (a.stride==b.stride) && (a.padding==b.padding)
const Pool = PoolLayer

#
# Dropout Layers
#
mutable struct DropoutLayer <: Layer
    prob::Float64
end
DropoutLayer() = DropoutLayer(0.1)
operator(L::DropoutLayer) = (x) -> dropout(x, L.prob)
nparams(L::DropoutLayer) = 0
nparams(L::DropoutLayer, indims) = 0
string(L::DropoutLayer) = "Dropout($(L.prob))"
outdims(L::DropoutLayer, indims) = indims
weights(L::DropoutLayer, indims) = ()
flops(l::DropoutLayer, indims) = prod(indims) # TODO
==(a::DropoutLayer, b::DropoutLayer) = a.prob == b.prob
const Dropout = DropoutLayer

#
# Batchnorm Layers
#
mutable struct BatchnormLayer <: Layer
    moments::Knet.BNMoments
end
BatchnormLayer() = BatchnormLayer(bnmoments())
operator(L::BatchnormLayer) = (x, w) -> batchnorm(x, L.moments, w)
nparams(L::BatchnormLayer) = 1
nparams(L::BatchnormLayer, indims) = indims[3]
string(L::BatchnormLayer) = "Batchnorm()"
outdims(L::BatchnormLayer, indims) = indims
weights(L::BatchnormLayer, indims) = (bnparams(indims[3]),)
flops(L::BatchnormLayer, indims) =  prod(indims)  # TODO
==(a::BatchnormLayer, b::BatchnormLayer) = true
const Batchnorm = BatchnormLayer

#
# Bias layer (add vector)
#
struct  BiasLayer <: Layer end
operator(L::BiasLayer) = (x, w) -> x .+ w
nparams(L::BiasLayer) = 1
nparams(L::BiasLayer, indims) =  prod(indims[1:end-1])
string(L::BiasLayer) = "Bias()"
outdims(L::BiasLayer, indims) = indims
weights(L::BiasLayer, indims) = (zeros(indims[1:end-1]...),)
flops(L::BiasLayer, indims) = prod(indims)
==(a::BiasLayer, b::BiasLayer) = true
const Bias = BiasLayer

#
# Deconvolution Layers  (TODO)
#
mutable struct DeconvLayer <: Layer
    window::Tuple{Int,Int}
    outchan::Int
    stride::Int
    padding::Int
end
DeconvLayer(window::Tuple{Int,Int}, outchan) =
    DeconvLayer(window::Tuple{Int,Int}, outchan, 1, 0)  # default: stride=1, padding=0
DeconvLayer(w::Int, outchan) = DeconvLayer((w,w), outchan)
DeconvLayer(w::Int, outchan, stride, padding) = DeconvLayer((w,w), outchan, stride, padding)
operator(L::DeconvLayer) = (x, w, b)-> deconv4(w, x, padding=L.padding, stride=L.stride) .+ b
nparams(L::DeconvLayer) = 2   # TODO: rename this to nweights?
nparams(L::DeconvLayer, indims) = prod(L.window)* indims[3] * L.outchan
string(L::DeconvLayer) = "Deconv$(length(L.window))D($(L.window), $(L.outchan), $(L.stride), $(L.padding))"
function outdims(L::DeconvLayer, X)
# If w has dimensions (W1,W2,...,O,I) and x has
  # dimensions (X1,X2,...,I,N), the result y will have dimensions (Y1,Y2,...,O,N) where
    Y1 = L.window[1] + L.stride*(X[1]-1)-2L.padding
    Y2 = L.window[2] + L.stride*(X[2]-1)-2L.padding
    O = L.outchan
    N = X[3]
    (Y1, Y2, O, N)
end
weights(L::DeconvLayer, indims) = (xavier(L.window[1], L.window[2], indims[3], L.outchan),zeros(1,1,L.outchan,1))
function flops(L::DeconvLayer, indims)
    mw = prod(L.window)
    mw = mw + mw - 1
    return prod(indims[1:2])*mw*L.outchan
end
==(a::DeconvLayer, b::DeconvLayer) = (a.window==b.window) && (a.outchan==b.outchan) && (a.stride==b.stride) && (a.padding==b.padding)
const Deconv = DeconvLayer
const Deconv1D = DeconvLayer
const Deconv2D = DeconvLayer
const Deconv3D = DeconvLayer

#
# NeuralNet and Layer methods
#
operator(A::NeuralNet) = function (w, x)
    i = 1
    for L in A.layers
        n = nparams(L)
        x = operator(L)(x, w[i:i+n-1]...)
        i += n
    end
    return x
end
function weights(net::NeuralNet, indims; atype=Array{Float32})
    #kaiming(h, w, i, o) = sqrt(2/(w*h*o)) .* randn(h, w, i, o)
    W = Any[]
    D = indims  # running value of data size as it passes through net
    for L in net.layers
        push!(W, weights(L, D)...)
        #info(L, " -> ", size(W[end]))
        D = outdims(L, D)
    end
    np = sum([length(w) for w in W])
    return (map(a -> convert(atype, a), W), np)
end

function +(A::Array{Layer,1}, B::Array{Layer,1})
    m = length(A)
    n = length(B)
    C = Array{Layer}(undef, m+n)
    C[1:m] = copy(A)
    C[m+1:m+n] = copy(B)
    return C
end
+(A::NeuralNet, B::NeuralNet) = NeuralNet(A.layers + B.layers)
function *(n::Int, L::Layer)
    A = Array{Layer}(undef, n)
    for i in 1:n
        A[i] = L
    end
    return A
end
function *(n::Int, A::Array{Layer,1})
    m = n*length(A)
    B = Array{Layer}(undef, m)
    for i in 1:m
        @info "$i <- $((i-1)%length(A)+1)"
        B[i] = A[(i-1) % length(A) + 1]
    end
    return B
end
*(n::Int, A::NeuralNet) = NeuralNet(n*A.layers)
function ==(A::NeuralNet, B::NeuralNet)
    if length(A.layers) != length(B.layers)
        return false
    else
        return all(A.layers .== B.layers)
    end
end

string(A::NeuralNet) = "NeuralNet(Layer[" * join([string(x) for x in A.layers], ",") * "])"
Base.show(io::IO, A::NeuralNet) = print(io, string(A))

function Base.show(io::IO, ::MIME"text/plain", A::NeuralNet)
    println(io, "$(depth(A))-layer NeuralNet:")
    for (i, L) in enumerate(A.layers)
        i < depth(A) ? println(io, "  ├ $(string(L)),") : print(io, "  └ $(string(L))")
    end
end

function repflow(A::NeuralNet, indims)
    n = zeros(depth(A)+1)
    Din = indims
    n[1] = prod(Din[1:end-1])
    for (i, L) in enumerate(A.layers)
        Dout = outdims(L, Din)
        n[i+1] = prod(Dout[1:end-1])
        Din = Dout
    end
    return n ./ n[1]
end
function dimflow(A::NeuralNet, indims)
    n = zeros(depth(A)+1)
    D = indims
    @info D
    for L in A.layers
        D = outdims(L, D)
        @info "$L -> $D"
    end
end
function flops(A::NeuralNet, indims::NTuple{4,Int})
    # approximate FLOPS of network
    D = indims
    n = 0
    for (k, L) in enumerate(A.layers)
        n += flops(L, D)
        D = outdims(L, D)
    end
    return n
end

Base.isvalid(dims::NTuple{N,Int}) where N = all(dims .> 0)
Base.isvalid(L::Layer, indims) = isvalid(outdims(L, indims))
function Base.isvalid(A::Array{Layer}, indims)
    dims = indims
    gonelinear = false
    for L in A
        if gonelinear && (typeof(L) == ConvLayer || typeof(L) == PoolLayer ||
            typeof(L) == BatchnormLayer)
            #warn("Conv, Pool, or Batchnorm after Linear is INVALID.")
            return false
        elseif !gonelinear && typeof(L) == LinearLayer
            gonelinear = true
        end
        dims = outdims(L, dims)
        isvalid(dims) || return false
    end
    return true
end
Base.isvalid(A::NeuralNet) = Base.isvalid(A.layers)

function nparams(net::NeuralNet, indims)
    n = 0
    D = indims  # running value of data size as it passes through net
    for L in net.layers
        n += nparams(L, D)
        D = outdims(L, D)
    end
    return n
end

#
# TRAINING AND DATA LOADING HELPERS
#

include("mnist.jl")

xtrn, ytrn, xtst, ytst = mnist()

function train(net::NeuralNet; epochs=10, fast=true, lr=0.001, seed=0xc0ffee,
    optfunc=Adam, ftrain=1.0, atype=KnetArray{Float32})
    Random.seed!(seed)
    gpuid = 0
    if gpu() >= 0 && atype == KnetArray{Float32}
        gpuid = myid() % Knet.gpuCount()
        gpu(gpuid) # activate appropriate GPU
        device="gpu$gpuid"
        atype = KnetArray{Float32}
    else
        device="cpu"
        atype = Array{Float32}
    end
    #infoprefix="$(gethostname())$(myid())$device: "
    @info "received $net"
    batchsize = 100
    Ntrain = round(Int, size(xtrn,4)*ftrain)
    dtrn = minibatch(xtrn[:,:,1,1:Ntrain], ytrn[1:Ntrain], batchsize; xtype=atype)  # keep this on CPU for Augmentor
    dtst = minibatch(xtst, ytst, batchsize; xtype=atype)
    nx, ny, nz = size(xtrn)[1:3]
    indims = (nx, ny, nz, 1)
    (w, np) = weights(net, indims, atype=atype)

    predict = operator(net)
    loss(w, x, ygold) = nll(predict(w, x), ygold)
    lossgradient = grad(loss)
    params = Array{Any}(undef, length(w))
    for k in 1:length(w)
        params[k] = optfunc(lr=lr)
    end

    if !fast
        @info "epoch 0: $(accuracy(w,dtst,predict))"
    end
    xaug = zeros(Float32, nx, ny, 1, batchsize)
    accvtime = zeros(epochs)
    traintime = time()
    for epoch in 1:epochs
        for (x, y) in dtrn
            #x = xtmp
            x = reshape(x, (nx, ny, nz, batchsize))
            #info("type(x): $(typeof(x)), type(y): $(typeof(y)), type(w): $(typeof(w))")
            #info(size(x))
            g = lossgradient(w, x, y)
            update!(w, g, params)
        end
        if !fast
            accvtime[epoch] = accuracy(w,dtst,predict)
            @info "epoch $epoch: $(accvtime[epoch])"
        end
    end
    if gpu() >= 0
        Knet.cudaDeviceSynchronize()
    end
    traintime = time() - traintime
    testacc = accuracy(w, dtst, predict)
    @info "Test accuracy = $testacc, training time = $traintime"
    if !fast
        @info "Accuracy vs Epoch:"
        println(lineplot(accvtime, color=:green))
    end
    return (testacc, traintime, np)
end
train(A::Array{Layer}; kwargs...) = train(NeuralNet(A); kwargs...)

# Example NeuralNets

mnist_mlp = NeuralNet(Layer[Dense(128), Bias(), ReLU(), Dense(64), Bias(), ReLU(), Dense(10)])

mnist_lenet = NeuralNet(Layer[
        Conv2D(5, 20), Tanh(), Pool(),
        Conv2D(5, 50), Tanh(), Pool(),
        Dense(500), Tanh(),
        Dense(10)
    ])

function test(net::NeuralNet = mnist_lenet; kwargs...)
    #show(STDOUT, "text/plain", net)
    acc, t = train(net; kwargs...)
end

end

if PROGRAM_FILE == "KnetLayers.jl"
    #KnetLayers.dimflow(KnetLayers.mnist_lenet,(28,28,1,1))
    KnetLayers.test(KnetLayers.mnist_mlp, fast=false)
    KnetLayers.test(KnetLayers.mnist_lenet, fast=false)
end

max_stars_repo_name: davidssmith/KnetLayers

max_issues_repo_name: davidssmith/KnetLayers

max_forks_repo_name: davidssmith/KnetLayers


text:
"""
    struct ProductSpace{S<:ElementarySpace, N} <: CompositeSpace{S}

A `ProductSpace` is a tensor product space of `N` vector spaces of type
`S<:ElementarySpace`. Only tensor products between [`ElementarySpace`](@ref) objects of the
same type are allowed.
"""
struct ProductSpace{S<:ElementarySpace, N} <: CompositeSpace{S}
    spaces::NTuple{N, S}
end
ProductSpace(spaces::Vararg{S,N}) where {S<:ElementarySpace, N} =
    ProductSpace{S,N}(spaces)
ProductSpace{S,N}(spaces::Vararg{S,N}) where {S<:ElementarySpace, N} =
    ProductSpace{S,N}(spaces)
ProductSpace{S}(spaces) where {S<:ElementarySpace} = ProductSpace{S,length(spaces)}(spaces)
ProductSpace(P::ProductSpace) = P

# Corresponding methods
#-----------------------
"""
    dims(::ProductSpace{S,N}) -> Dims{N} = NTuple{N,Int}

Return the dimensions of the spaces in the tensor product space as a tuple of integers.
"""
dims(P::ProductSpace) = map(dim, P.spaces)
dim(P::ProductSpace, n::Int) = dim(P.spaces[n])
dim(P::ProductSpace) = prod(dims(P))

Base.axes(P::ProductSpace) = map(axes, P.spaces)
Base.axes(P::ProductSpace, n::Int) = axes(P.spaces[n])

dual(P::ProductSpace{<:ElementarySpace,0}) = P
dual(P::ProductSpace) = ProductSpace(map(dual, reverse(P.spaces)))

# Base.conj(P::ProductSpace) = ProductSpace(map(conj, P.spaces))

function Base.show(io::IO, P::ProductSpace{S}) where {S<:ElementarySpace}
    spaces = P.spaces
    if length(spaces) == 0
        print(io,"ProductSpace{", S, ",0}")
    end
    if length(spaces) == 1
        print(io,"ProductSpace")
    end
    print(io,"(")
    for i in 1:length(spaces)
        i==1 || print(io," ⊗ ")
        show(io, spaces[i])
    end
    print(io,")")
end

# more specific methods
"""
    sectors(P::ProductSpace{S,N}) where {S<:ElementarySpace}

Return an iterator over all possible combinations of sectors (represented as an
`NTuple{N,sectortype(S)}`) that can appear within the tensor product space `P`.
"""
sectors(P::ProductSpace) = _sectors(P, sectortype(P))
_sectors(P::ProductSpace{<:ElementarySpace, N}, ::Type{Trivial}) where {N} =
    (ntuple(n->Trivial(), StaticLength{N}()),) # speed up sectors for ungraded spaces
_sectors(P::ProductSpace{<:ElementarySpace, N}, ::Type{<:Sector}) where {N} =
    product(map(sectors, P.spaces)...)

"""
    hassector(P::ProductSpace{S,N}, s::NTuple{N,sectortype(S)}) where {S<:ElementarySpace}
    -> Bool

Query whether `P` has a non-zero degeneracy of sector `s`, representing a combination of
sectors on the individual tensor indices.
"""
hassector(V::ProductSpace{<:ElementarySpace,N}, s::NTuple{N}) where {N} =
    reduce(&, map(hassector, V.spaces, s); init = true)

"""
    dims(P::ProductSpace{S,N}, s::NTuple{N,sectortype(S)}) where {S<:ElementarySpace}
    -> Dims{N} = NTuple{N,Int}

Return the degeneracy dimensions corresponding to a tuple of sectors `s` for each of the
spaces in the tensor product `P`.
"""
dims(P::ProductSpace{<:ElementarySpace, N}, sector::NTuple{N,<:Sector}) where {N} =
    map(dim, P.spaces, sector)

"""
    dims(P::ProductSpace{S,N}, s::NTuple{N,sectortype(S)}) where {S<:ElementarySpace}
    -> Int

Return the total degeneracy dimension corresponding to a tuple of sectors for each of the
spaces in the tensor product, obtained as `prod(dims(P, s))``.
"""
dim(P::ProductSpace{<:ElementarySpace, N}, sector::NTuple{N,<:Sector}) where {N} =
    reduce(*, dims(P, sector); init = 1)

Base.axes(P::ProductSpace{<:ElementarySpace,N}, sectors::NTuple{N,<:Sector}) where {N} =
    map(axes, P.spaces, sectors)

"""
    blocksectors(P::ProductSpace)

Return an iterator over the different unique coupled sector labels, i.e. the different
fusion outputs that can be obtained by fusing the sectors present in the different spaces
that make up the `ProductSpace` instance.
"""
function blocksectors(P::ProductSpace{S,N}) where {S,N}
    G = sectortype(S)
    if G == Trivial
        return TrivialOrEmptyIterator(dim(P) == 0)
    end
    bs = Vector{G}()
    if N == 0
        push!(bs, one(G))
    elseif N == 1
        for s in sectors(P)
            push!(bs, first(s))
        end
    else
        for s in sectors(P)
            for c in ⊗(s...)
                if !(c in bs)
                    push!(bs, c)
                end
            end
        end
        # return foldl(union!, Set{G}(), (⊗(s...) for s in sectors(P)))
    end
    return bs
end

"""
    blockdim(P::ProductSpace, c::Sector)

Return the total dimension of a coupled sector `c` in the product space, by summing over
all `dim(P, s)` for all tuples of sectors `s::NTuple{N,<:Sector}` that can fuse to  `c`,
counted with the correct multiplicity (i.e. number of ways in which `s` can fuse to `c`).
"""
function blockdim(P::ProductSpace, c::Sector)
    sectortype(P) == typeof(c) || throw(SectorMismatch())
    d = 0
    for s in sectors(P)
        ds = dim(P, s)
        d += length(fusiontrees(s, c))*ds
    end
    return d
end

Base.:(==)(P1::ProductSpace, P2::ProductSpace) = (P1.spaces == P2.spaces)

Base.hash(P::ProductSpace, h::UInt) = hash(P.spaces, h)

# Default construction from product of spaces
#---------------------------------------------
⊗(V1::S, V2::S) where {S<:ElementarySpace}= ProductSpace((V1, V2))
⊗(P1::ProductSpace{S}, V2::S) where {S<:ElementarySpace} =
    ProductSpace(tuple(P1.spaces..., V2))
⊗(V1::S, P2::ProductSpace{S}) where {S<:ElementarySpace} =
    ProductSpace(tuple(V1, P2.spaces...))
⊗(P1::ProductSpace{S}, P2::ProductSpace{S}) where {S<:ElementarySpace} =
    ProductSpace(tuple(P1.spaces..., P2.spaces...))
⊗(P::ProductSpace{S,0}, ::ProductSpace{S,0}) where {S<:ElementarySpace} = P
⊗(P::ProductSpace{S}, ::ProductSpace{S,0}) where {S<:ElementarySpace} = P
⊗(::ProductSpace{S,0}, P::ProductSpace{S}) where {S<:ElementarySpace} = P
⊗(V::ElementarySpace) = ProductSpace((V,))
⊗(P::ProductSpace) = P

# unit element with respect to the monoidal structure of taking tensor products
"""
    one(::S) where {S<:ElementarySpace} -> ProductSpace{S,0}
    one(::ProductSpace{S}) where {S<:ElementarySpace} -> ProductSpace{S,0}

Return a tensor product of zero spaces of type `S`, i.e. this is the unit object under the
tensor product operation, such that `V ⊗ one(V) == V`.
"""
Base.one(V::VectorSpace) = one(typeof(V))
Base.one(::Type{<:ProductSpace{S}}) where {S<:ElementarySpace} = ProductSpace{S,0}(())
Base.one(::Type{S}) where {S<:ElementarySpace} = ProductSpace{S,0}(())

Base.convert(::Type{<:ProductSpace}, V::ElementarySpace) = ProductSpace((V,))
Base.:^(V::ElementarySpace, N::Int) = ProductSpace{typeof(V), N}(ntuple(n->V, N))
Base.:^(V::ProductSpace, N::Int) = ⊗(ntuple(n->V, N)...)
Base.literal_pow(::typeof(^), V::ElementarySpace, p::Val{N}) where N =
    ProductSpace{typeof(V), N}(ntuple(n->V, p))
Base.convert(::Type{S}, P::ProductSpace{S,0}) where {S<:ElementarySpace} = oneunit(S)
Base.convert(::Type{S}, P::ProductSpace{S}) where {S<:ElementarySpace} = fuse(P.spaces...)
fuse(P::ProductSpace{S,0}) where {S<:ElementarySpace} = oneunit(S)
fuse(P::ProductSpace{S}) where {S<:ElementarySpace} = fuse(P.spaces...)

# Functionality for extracting and iterating over spaces
#--------------------------------------------------------
Base.length(P::ProductSpace) = length(P.spaces)
Base.getindex(P::ProductSpace, n::Integer) = P.spaces[n]
# Base.getindex(P::ProductSpace{S}, I::NTuple{N,Integer}) where {S<:ElementarySpace,N} =
#     ProductSpace{S,N}(TupleTools.getindices(P.spaces, I))

Base.iterate(P::ProductSpace, args...) = Base.iterate(P.spaces, args...)
# Base.indexed_iterate(P::ProductSpace, args...) = Base.indexed_iterate(P.spaces,  args...)

Base.eltype(::Type{<:ProductSpace{S}}) where {S<:ElementarySpace} = S
Base.eltype(P::ProductSpace) = eltype(typeof(P))

Base.IteratorEltype(::Type{<:ProductSpace}) = Base.HasEltype()
Base.IteratorSize(::Type{<:ProductSpace}) = Base.HasLength()


text:
using Documenter, HomotopyContinuation

makedocs(
    sitename = "HomotopyContinuation.jl",
    pages = [
        "Introduction" => "index.md",
        "Problem formulation" => [
            "ModelKit" => "model_kit.md",
            "Linear and Affine Subspaces" => "linear_affine.md",
            "Systems and Homotopies" => "systems_homotopies.md",
        ],
        "Solving systems" => [
            "Solve" => "solve.md",
            "Results" => "result.md",
            "Examples" => "solve_examples.md",
            "Start systems" => "start_systems.md",
        ],
        "Trackers" => ["Tracker" => "tracker.md", "EndgameTracker" => "endgame_tracker.md"],
        "Miscellaneous" => "misc.md",
    ],
    format = Documenter.HTML(prettyurls = get(ENV, "CI", nothing) == "true"),
)

deploydocs(
    repo = "github.com/saschatimme/HomotopyContinuation.jl.git",
    push_preview = false,
)


text:
Base.rand(X::Interval{T}) where {T} = X.lo + rand(T) * (X.hi - X.lo)

Base.rand(X::IntervalBox) = rand.(X)


text:
module MaximumSubMatrix

using DataStructures

export maximum_rectagular_area,
    maximum_rectagular_submatrix

include("histogram.jl")
include("submatrix.jl")

end


text:
const MDH_NUMBEROFEVALINFOMASK = 2
const MDH_NUMBEROFICEPROGRAMPARA_VB = 4
const MDH_NUMBEROFICEPROGRAMPARA_VD = 24
const MDH_FREEHDRPARA_VB = 4
const MDH_DMA_LENGTH_MASK = 0x01FFFFFF#L
const MDH_PACK_BIT_MASK = 0x02000000#L
const MDH_ENABLE_FLAGS_MASK = 0xFC000000#L
const MDH_SYNCDATA = 0x00000020#L

@enum PMU_Type begin
	END =  0x01FF0000
	ECG1 = 0x01010000
	ECG2 = 0x01020000
	ECG3 = 0x01030000
	ECG4 = 0x01040000
	PULS = 0x01050000
	RESP = 0x01060000
	EXT1 = 0x01070000
	EXT2 = 0x01080000
end

#=
enum class Trajectory {
  TRAJECTORY_CARTESIAN = 0x01,
  TRAJECTORY_RADIAL    = 0x02,
  TRAJECTORY_SPIRAL    = 0x04,
  TRAJECTORY_BLADE     = 0x08
}; =#

struct mdhLC
  ushLine::UInt16
  ushAcquisition::UInt16
  ushSlice::UInt16
  ushPartition::UInt16
  ushEcho::UInt16
  ushPhase::UInt16
  ushRepetition::UInt16
  ushSet::UInt16
  ushSeg::UInt16
  ushIda::UInt16
  ushIdb::UInt16
  ushIdc::UInt16
  ushIdd::UInt16
  ushIde::UInt16
end

struct mdhCutOff
  ushPre::UInt16
  ushPost::UInt16
end

struct mdhSlicePosVec
  flSag::Float32
  flCor::Float32
  flTra::Float32
end

struct PMUdata
	data::UInt16
	trigger::UInt16
end

struct mdhSliceData
  sSlicePosVec::mdhSlicePosVec
  aflQuaternion::NTuple{4,Float32}
end

# This is the VB line header
struct sMDH
  ulFlagsAndDMALength::UInt32
  lMeasUID::UInt32
  ulScanCounter::UInt32
  ulTimeStamp::UInt32
  ulPMUTimeStamp::UInt32
  aulEvalInfoMask::NTuple{2,UInt32}
  ushSamplesInScan::UInt16
  ushUsedChannels::UInt16
  sLC::mdhLC
  sCutOff::mdhCutOff

  ushKSpaceCentreColumn::UInt16
  ushCoilSelect::UInt16
  fReadOutOffcentre::Float32
  ulTimeSinceLastRF::UInt32
  ushKSpaceCentreLineNo::UInt16
  ushKSpaceCentrePartitionNo::UInt16
  aushIceProgramPara::NTuple{4,UInt16}
  aushFreePara::NTuple{4,UInt16}

  sSliceData::mdhSliceData

  ushChannelId::UInt16
  ushPTABPosNeg::UInt16
end

# This is the VD line header
struct sScanHeader
	  ulFlagsAndDMALength::UInt32
	  lMeasUID::Int32
	  ulScanCounter::UInt32
	  ulTimeStamp::UInt32
	  ulPMUTimeStamp::UInt32
	  ushSystemType::UInt16
	  ulPTABPosDelay::UInt16
	  lPTABPosX::Int32
	  lPTABPosY::Int32
	  lPTABPosZ::Int32
	  ulReserved1::UInt32
	  aulEvalInfoMask::NTuple{2,UInt32}
	  ushSamplesInScan::UInt16
	  ushUsedChannels::UInt16
	  sLC::mdhLC
	  sCutOff::mdhCutOff
	  ushKSpaceCentreColumn::UInt16
	  ushCoilSelect::UInt16
	  fReadOutOffcentre::Float32
	  ulTimeSinceLastRF::UInt32
	  ushKSpaceCentreLineNo::UInt16
	  ushKSpaceCentrePartitionNo::UInt16
	  sSliceData::mdhSliceData
	  aushIceProgramPara::NTuple{24,UInt16}
	  aushReservedPara::NTuple{4,UInt16}
	  ushApplicationCounter::UInt16
	  ushApplicationMask::UInt16
	  ulCRC::UInt32
end

struct sChannelHeader
  ulTypeAndChannelLength::UInt32
  lMeasUID::Int32
  ulScanCounter::UInt32
  ulReserved1::UInt32
  ulSequenceTime::UInt32
  ulUnused2::UInt32
  ulChannelId::UInt16
  ulUnused3::UInt16
  ulCRC::UInt32
end

struct MrParcRaidFileEntry
  measId_::UInt32
  fileId_::UInt32
  off_::UInt64
  len_::UInt64
  patName_::NTuple{64,UInt8}
  protName_::NTuple{64,UInt8}
end

struct MrParcRaidFileHeader
  hdSize_::UInt32
  count_::UInt32
end

#=
typedef struct
{
  sMDH mdh;
  void* previous;
  void* next;
  float* data;
} SiemensMdhNode;=#

struct SiemensBaseParameters
  matrix_size::NTuple{3,UInt32}
  pat_matrix_size::NTuple{3,UInt32}
  base_resolution::UInt32
  phase_encoding_lines::UInt32
  partitions::UInt32
  dimensions::UInt32
  phase_resolution::Float32
  slice_resolution::Float32
  dwell_time_us::Float32
  acceleration_factor_pe::UInt32
  acceleration_factor_3d::UInt32
end


text:
using Documenter, Jets, LinearAlgebra, Random

makedocs(
    sitename="Jets.jl",
    modules=[Jets],
    pages = [ "index.md", "reference.md" ]
)

deploydocs(
    repo = "github.com/ChevronETC/Jets.jl.git"
)


text:
module TestAutomaticStateSelection

using Modia
using Modia.Electric

# Desired:
#   using ModiaMath: plot
#   using Test
#
# In order that these packages need not to be defined in the user environment, they are included via Modia:
using Modia.ModiaMath: plot

@static if VERSION < v"0.7.0-DEV.2005"
    using Base.Test
else
    using Modia.Test
end

const logSimulation=true

@model TwoConnectedInertias begin
    J1 = 2.0
    J2 = 3.0
    w1 = Float(size=(), start=1.0)
    w2 = Float(size=(), start=1.0)
    tau = Float(size=())
    t   = Float(size=())
    @equations begin
        der(t) = 1.0
        J1*der(w1) = sin(t) - tau
        J2*der(w2) = tau
        w1 = w2
    end
end
result = simulate(TwoConnectedInertias, 3.0; logTranslation=true, logSimulation=logSimulation, tearing=true, removeSingularities=false, automaticStateSelection=true)
plot(result, ("w1", "w2"), figure=1)

@model TwoInertiasConnectedViaIdealGear begin
    J1 = 2.0
    J2 = 3.0
    ratio = 4.0
    w1 = Float(size=(), start=1.0)
    w2 = Float(size=(), start=1.0)
    tau = Float(size=())
    t   = Float(size=())
    @equations begin
        der(t) = 1.0
        J1*der(w1) = sin(t) - ratio*tau
        J2*der(w2) = tau
        w1 = ratio*w2
    end
end
result = simulate(TwoInertiasConnectedViaIdealGear, 3.0; logTranslation=true, logSimulation=logSimulation, tearing=true, removeSingularities=true, automaticStateSelection=true)
plot(result, ("w1", "w2"), figure=2)

@model ParallelCapacitors1 begin
    C1 = Capacitor(C=1.1, v=Float(start=1.0))
    C2 = Capacitor(C=2.2, v=Float(state=false))
    ground = Ground()
    @equations begin
        connect(C1.p, C2.p)
        connect(C1.n, C2.n)
        connect(C1.n, ground.p)
    end
end

result = simulate(ParallelCapacitors1, 1; logTranslation=true, logSimulation=logSimulation, tearing=true, removeSingularities=true, automaticStateSelection=false)
plot(result, ("C1.v", "C2.v"), figure=3)

@model ParallelCapacitors2 begin
    C1 = Capacitor(C=1.1, v=Float(start=1.0))
    C2 = Capacitor(C=2.2, v=Float(start=1.0))
    ground = Ground()
    @equations begin
        connect(C1.p, C2.p)
        connect(C1.n, C2.n)
        connect(C1.n, ground.p)
    end
end

result = simulate(ParallelCapacitors2, 1; logTranslation=true, logSimulation=logSimulation, tearing=true, removeSingularities=false, automaticStateSelection=true)
plot(result, ("C1.v", "C2.v"), figure=4)

@model ParallelCapacitors2b begin
    C1 = 1e-3
    C2 = 2e-3
    u1 = Float(size=(), start=1.0)
    u2 = Float(size=(), state=false)
    i1 = Float(size=())
    v1 = Float(size=())
    v0 = Float(size=())
@equations begin
    C1*der(u1) = i1
    C2*der(u2) = -i1
    u1 = v1 - v0
    u2 = v1 - v0
    v0 = 0
    end
end
result = simulate(ParallelCapacitors2b , 1.0; logTranslation=true, logSimulation=logSimulation, tearing=true, removeSingularities=true, automaticStateSelection=false)
plot(result, ("u1", "u2", "i1", "v1"), figure=6)

# Does not compile
@model TwoInertiasConnectedViaIdealGearWithPositionConstraints begin
    J1 = 2.0
    J2 = 3.0
    ratio = 4.0
    phi1 = Float(size=(), start=1.0, fixed=true)
    phi2 = Float(size=(), start=1.0)
    w1 = Float(size=(), start=1.0, fixed=true)
    w2 = Float(size=(), start=1.0, fixed=true)
    tau = Float(size=())
    t   = Float(size=())
    @equations begin
        der(t) = 1.0
        w1 = der(phi1)
        w2 = der(phi2)
        J1*der(w1) = sin(t) - ratio*tau
        J2*der(w2) = tau
        phi1 = ratio*phi2
    end
end
result = simulate(TwoInertiasConnectedViaIdealGearWithPositionConstraints, 3.0; logTranslation=true, logSimulation=logSimulation, tearing=true, removeSingularities=false, automaticStateSelection=true)
plot(result, [("phi1", "phi2"), ("w1", "w2")], figure=7)
println("after plot")

end


text:
mutable struct VNamedD_misfit{T}
	x::Vector{NamedD{T}} # modelled data
	y::Vector{NamedD{T}} # observed data
	w::Vector{NamedD{T}} # weights
	dJx::Vector{NamedD{T}} # gradient
	ynorm::Float64 # normalize functional with energy of y
end

function VNamedD_misfit(x, y; w=nothing)

	if(w===nothing)
		w=deepcopy(y);
		fill!(w, 1.0)
	end
	!(issimilar(w,y)) && error("weights have to be similar to y")
	!(issimilar(x,y)) && error("cannot measure LS misfit b/w dissimilar data")

	dJx=deepcopy(x); fill!(dJx,0.0)

	ynorm = dot(y, y)
	(ynorm == 0.0) && error("y cannot be zero")

	pa=VNamedD_misfit(x,y,w,dJx,ynorm)

	return pa
end

function func_grad!(pa::VNamedD_misfit, grad=nothing)

	# some aliases

	y=pa.y
	x=pa.x

	J = 0.0;
	for iss in 1:length(x)
		for ifield=names(x[iss].d)[1]
			xr=x[iss].d[ifield]
			yr=y[iss].d[ifield]
			wr=pa.w[iss].d[ifield]

			# using Distances eqeuclidean here
			if(grad===nothing)
				# JJ=squared_euclidean!(nothing,xr,yr,wr,norm_flag=false)
			elseif(grad==:dJx)
				dJxr=pa.dJx[iss].d[ifield]
				# JJ=squared_euclidean!(dJxr,xr,yr,wr,norm_flag=false)
			else
				error("invalid grad")
			end
			J += JJ
		end
	end
	return J
end

#=

"""
Calculate the distance between the observed data `y` and the calculated data `x`.
The time grid of the observed data can be different from that of the modelled data.
The acqistion ageometry of both the data sets should be the same.

If `J` is the distance, the gradient of the misfit w.r.t to the calculated data is returned as `dJx`
* `w` used for data preconditioning
* `coupling` source and receiver coupling functions
"""
mutable struct VNamedD_misfit_ssf
	x::VNamedD # modelled data
	y::VNamedD # observed data
	pa::VNamedD_misfit
	dJx::VNamedD # gradient w.r.t. x
	xr::VNamedD # modelled data after resampling
	xrc::VNamedD # modelled data after resampling and convolution with source coupling
	dJxr::VNamedD # gradient w.r.t. xr
	dJxrc::VNamedD # gradient w.r.t. xr
	dJx::VNamedD # gradient w.r.t. x
	dJssf::Matrix{Vector{Float64}} # gradient w.r.t source filters
	ynorm::Float64 # normalize functional with energy of y
	coup::Coupling.VNamedD
	paconvssf::Vector{FBD.P_conv{Float64,2,2,1}} # convolutional model for source filters
	paconvrf::FBD.P_conv{Float64,1} # convolutional model for receiver filters
	pacse::Matrix{FBD.VNamedD_misfit_xcorr}
	func::Matrix{Function} # function to compute misfit for every ss and fields
	painterp::Interpolation.Param{Float64}
	interp_flag # decide if interpolation is necessary or not
end

function VNamedD_misfit_ssf(x, y; w=nothing, coup=nothing, func_attrib=:cls)

	if(coup===nothing)
		 coup=Coupling.VNamedD_delta(y.tgrid,[0.1,0.1],[0.0, 0.0], [:P], y.ageom)
	end

	paconvssf=[FBD.P_conv(ssize=[coup.tgridssf.nx],
			dsize=[length(y.tgrid),y.ageom.nr[iss]],
			gsize=[length(y.tgrid),y.ageom.nr[iss]],
		      slags=coup.ssflags,
		      dlags=[length(y.tgrid)-1, 0],
		      glags=[length(y.tgrid)-1, 0]) for iss in 1:y.ageom.nss]

	dJssf=deepcopy(coup.ssf)

	pacls=VNamedD_misfit(VNamedD_zeros(y), y; w=w)

	!(isequal(x.ageom, y.ageom)) && error("observed and modelled data should have same ageom")
	!(isequal(x.fields, y.fields)) && error("observed and modelled data should have same fields")

	xr=VNamedD_zeros(y)
	xrc=VNamedD_zeros(y)
	dJxr=VNamedD_zeros(y)
	dJxrc=VNamedD_zeros(y)
	dJx=VNamedD_zeros(x)

	ynorm = dot(y, y)
	(ynorm == 0.0) && error("y cannot be zero")

	dJxc=zeros(length(y.tgrid))

	if(func_attrib==:cls)
		pacse=[FBD.VNamedD_misfit_xcorr(1, 1,y=zeros(1,1)) for i in 1:2, j=1:2] # dummy
		func=[(dJx,x)->squared_euclidean!(dJx,x,y.d[iss,ifield],w.d[iss,ifield]) for iss in 1:y.ageom.nss, ifield=1:length(y.fields)]
	elseif(func_attrib==:xcorrcls)
		pacse=[FBD.VNamedD_misfit_xcorr(length(y.tgrid), y.ageom.nr[iss],y=y.d[iss,ifield]) for iss in 1:y.ageom.nss, ifield=1:length(y.fields)]
		func=[(dJx,x)->FBD.func_grad!(dJx,x,pacse[iss,ifield]) for iss in 1:y.ageom.nss, ifield=1:length(y.fields)]
	end

	pa=VNamedD_misfit(x,y,w,xr,xrc,dJxr,dJxrc,
		    dJx,dJssf,ynorm,coup,paconvssf, paconvrf, pacse, func, painterp, interp_flag)

	return pa
end

function func_grad!(pa::VNamedD_misfit_ssf, grad=nothing)

	tgrid = pa.x.tgrid;
	acq = pa.x.ageom;
	fields = pa.x.fields;
	nss = acq.nss;

	if(pa.interp_flag)
		# resample xr <-- x
		interp_spray!(pa.x, pa.xr, :interp, pa=pa.painterp)
		println("ffffff, HELEL")
	else
		copyto!(pa.xr,pa.x)
	end

	xr=pa.xr
	xrc=pa.xrc
	y=pa.y

	J = 0.0;
	for ifield=1:length(fields), iss=1:acq.nss
		xrr=xr.d[iss,ifield]
		xrcc=xrc.d[iss,ifield]
		wav=pa.coup.ssf[iss,ifield]

		nt=size(xrr,1)
		nr=size(xrr,2)

		paconv=pa.paconvssf[iss]
		# xrc <- xr apply source filter to xr
		FBD.mod!(paconv, :d, g=xrr, s=wav, d=xrcc)

		if(grad===nothing)
			JJ=pa.func[iss,ifield](nothing,  xrcc)
		elseif((grad==:dJx) || (grad==:dJssf))
			dJxrcc=pa.dJxrc.d[iss,ifield]
			JJ=pa.func[iss,ifield](dJxrcc,  xrcc)
		else
			error("invalid grad")
		end

		# dJxr <- dJxrc  apply adjoint of source filter to dJxc
		if(grad==:dJx)
			dJxrr=pa.dJxr.d[iss,ifield]
			dJxrcc=pa.dJxrc.d[iss,ifield]
			FBD.mod!(paconv, :g, g=dJxrr, s=wav, d=dJxrcc)
		end

		# dJssf <- dJxrc
		if(grad==:dJssf)
			dJwav=pa.dJssf[iss,ifield]
			FBD.mod!(paconv, :s, g=xrr, s=dJwav, d=dJxrcc)
		end
		J += JJ
	end

	if(pa.interp_flag)
		# spray dJx <-- dJxr
		interp_spray!(pa.dJx, pa.dJxr, :spray, pa=pa.painterp)
		println("ffffff, HELEL")
	else
		copyto!(pa.dJx,pa.dJxr)
	end

	(J == 0.0) && warn("misfit computed is zero")

	return J

end

=#


text: include("hpc.jl")

max_stars_repo_name: DTUComputeTONIA/SDRLS


text:
#######
### time stepping function

function time_hist(nsteps,tol_unb,model,tol,σ_hist,ϵ_hist,nstate,stateold,dt,npara,mpara,unkn,notunkn)

    ϵ_out=zeros(nsteps); σ_out=zeros(nsteps); σ_out2=zeros(nsteps);
    strainv=zeros(9); stressv=zeros(9); dstrain=zeros(9); strainold=zeros(9); stressold=zeros(9);
    stress_out=zeros(9); strain_out=zeros(9); statenew=zeros(nstate); lconv=1
    #println("ppp",notunkn)
    #println("qqq",unkn)
    nunkn=size(unkn,1)

    kalle=zeros(9)

    for n=1:nsteps

        stressv[unkn]=σ_hist[n]*ones(nunkn);
        strainv[notunkn]=ϵ_hist[n]*ones(nnotunkn);

        stress_out,strain_out,statenew,lconv=solve_stress_iteration(tol_unb,model,tol,strainold,stressold,nstate,stateold,strainv,dt,npara,mpara,stressv,unkn)

        #push!(ϵ_out, c)
        ϵ_out[n]=strain_out[1]
        #push!(σ_out, stress_out[1])
        σ_out[n]=stress_out[1]
        #push!(σ_out2,stress_out[2])
        σ_out2[n]=stress_out[2]

        stressv,strainv,stressold,strainold,stateold=update_variables(stress_out,strain_out,statenew)

    end

    #end time stepping function

    return ϵ_out,σ_out,σ_out2
end

function update_variables(stress_out,strain_out,statenew)
    stressv=stress_out*1.; strainv=strain_out*1.;
    stressold=stress_out*1.; strainold=strain_out*1.;
    stateold=statenew*1.

    return stressv,strainv,stressold,strainold,stateold

end

####### solve if some stress components are prescribed

function solve_stress_iteration(tol_unb,model,tol,strainold,stressold,nstate,stateold,strainv,dt,npara,mpara,stressv,unkn)

#(tol_unb::Float64,model::Int32,tol::Float64,strainold::Float64,stressold::Float64,stateold::Float64,strainv::Float64,dt::Float64,mpara::Float64,stressv::Float64,unkn::Int32)

  res_unb=1e10; niter=0
  stress_out=zeros(9); strain_out=zeros(9); statenew=zeros(nstate); lconv=1;
  #Array{Float64}(undef, 2)

    #
    while res_unb>tol_unb

        dstrain=strainv-strainold

        stress_out, statenew, stiffv, lconv = constitutive_driver(model,tol,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara)

        if (size(unkn,1)>0)

            stress_unbalance=stress_out[unkn]-stressv[unkn]
            res_unb=norm(stress_unbalance)
            niter=niter+1
            println("unb=  ",res_unb,"   niter=",niter) #,"   dstrain=",dstrain)
            #println("s11= ",stress_out[1])

            #Newton update
            strainv[unkn]=strainv[unkn]-inv(stiffv[unkn,unkn])*stress_unbalance

        else
            res_unb=0.e0
        end

    end #while

    strain_out=strainv

    return stress_out, strain_out, statenew, lconv

end

#############################

struct hookeisopar
    #constant, not updated for every element
    E::Float64
    ν::Float64
    C::Matrix{Float64}
end

#=function Hookeiso(E::Float64, ν::Float64, plainstrain::Bool)
        μ=E/(2*(1+ν))
        λ=E*ν/((1+ν)*(1-2*ν))
        if plainstrain
                C=[     2μ+λ    λ       0;
                        λ       2μ+λ  0;
                        0       0       μ]
        else
                C=2μ/(2μ+λ)*[   2(μ+λ)  λ       0;
                                λ       2(μ+λ)  0;
                                0       0       (2μ+λ)/2]
        end
        Hookeiso(E, ν, C)
end =#

#not used for 2D case
function hookeiso_stiff(E::AbstractFloat, ν::AbstractFloat)::Tensor{4,3,Float64}
        δ(i,j) = i==j ? 1.0 : 0.0
        μ=E/(2*(1+ν))
        λ=E*ν/((1+ν)*(1-2*ν))
        #C=Tensor{4,3,Float64}((i,j,k,l)->μ*(δ(i,l)*δ(j,k)+δ(i,k)*δ(j,l)) + λ*δ(i,j)*δ(k,l))
        C=Tensor{4,3,Float64}((i,j,k,l)->2*μ*(δ(i,k)*δ(j,l)) + λ*δ(i,j)*δ(k,l))
        return C
end

function hookeiso_stiff_GK(G::AbstractFloat, K::AbstractFloat)::Tensor{4,3,Float64}
        δ(i,j) = i==j ? 1.0 : 0.0
        μ=G
        λ=K-2*G/3
        C=Tensor{4,3,Float64}((i,j,k,l)->2*μ*(δ(i,k)*δ(j,l)) + λ*δ(i,j)*δ(k,l))
        return C
end

###############

function constitutive_driver(model,tol,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara)

    stressout=zeros(9); statenew=zeros(nstate); stiffv=zeros(9,9); lconv=1;

    if model==1

      stiffv=tovoigt(hookeiso_stiff(mpara[1],mpara[2]))
      stress_out=stressold+stiffv*dstrain
      statenew=stateold*1.
    elseif model==2

      stiffv=tovoigt(hookeiso_stiff(mpara[1],mpara[2]))
      stress_out=stressold+stiffv*dstrain
      #println(stress_out,stressold,"****")
      statenew=stateold*1.
      xinit=zeros(20)
      xinit[1:9]=stressold; xinit[10:19]=stateold; xinit[20]=0.
      stress_out, statenew, stiffv = local_problem(xinit,model,tol,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara)

    else model==3

      stiffv=tovoigt(hookeiso_stiff(mpara[1],mpara[2]))
      stress_out=stressold+stiffv*dstrain
      #println(stress_out,stressold,"****")
      statenew=stateold*1.
      xinit=zeros(9)
      xinit[1:9]=stressold;
      stress_out,statenew,stiffv=local_problem_ve(xinit,model,tol,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara)

    end

    return stress_out, statenew, stiffv, lconv

end
################# solve local problem
###  Here my plasticity code was .../ M Ekh
############ For local problem
#
function extract_statevariables_model_plast_prototype(stateold)

     kappaold=stateold[1]; alphaold=fromvoigt(Tensor{2,3},stateold[2:10]);
     return kappaold,alphaold
end

function collect_statevariables_model_plast_prototype(kappa,alpha)
     state=zeros(eltype(kappa),10)
     state[1]=kappa
     state[2:10]=tovoigt(alpha)
     return state
end

function extract_unknowns_model_plast_prototype(x)

     stress=fromvoigt(Tensor{2,3},x[1:9]); kappa=x[10]; alpha=fromvoigt(Tensor{2,3},x[11:19]); dlambda=x[20]
     return stress,kappa,alpha,dlambda
end
#

################# solve local problem viscoelasticity
function local_problem_ve(xinit,model,tol,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara)

    nunkn=size(xinit,1)
    iter=0; x=zeros(nunkn)
    x=xinit
    maxitr=50
    stress_out=zeros(9)
    statenew=zeros(nstate)

    R=zeros(eltype(x), nunkn)
    #dR=zeros(eltype(x), [20,20])

    #elastic trial step
    C=hookeiso_stiff(mpara[1],mpara[2])

    Jacob=zeros(nunkn,nunkn)
    while true; iter+=1

        R=local_unbalance_ve(x,model,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara)

        if norm(R)< tol
          Jacob=ForwardDiff.jacobian(y->local_unbalance_ve(y,model,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara),x)
          break
        end
        if iter > maxitr
                    error("Local problem did not converge aftter $maxitr iterations.")
        end
        dR=ForwardDiff.jacobian(y->local_unbalance_ve(y,model,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara),x)
    #   println("***  ",ForwardDiff.jacobian(y->local_unbalance(y,model,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara),x))
        #Δx = -dR\R
        #x += Δx
        #println(dR)
        x=x-dR\R

    end

    invJacob=inv(Jacob)
    ats=tovoigt(dcontract(fromvoigt(Tensor{4,3},invJacob[1:9,1:9]),C))

    stress=fromvoigt(Tensor{2,3},x[1:9]);
    statenew=stateold

    stress_out=tovoigt(stress)

    return stress_out,statenew,ats
end

############ Local problem
function local_unbalance_ve(x,model,strainold,stressold,nstate,stateold,dstrain,dt,npara,mpara)
     nunkn=size(x,1)
     Rr=zeros(eltype(x),nunkn)
     if model==3

      stress=fromvoigt(Tensor{2,3},x[1:9])

      C=hookeiso_stiff(mpara[1],mpara[2])
      Dv=hookeiso_stiff_GK(1/(2*mpara[3]),1/(2*mpara[4]))
      stresstrial=fromvoigt(Tensor{2,3},stressold)+dcontract(C,fromvoigt(Tensor{2,3},dstrain))
      Rstress=stress-stresstrial+dt*dcontract(dcontract(C,Dv),stress)
      Rr[1:9]=tovoigt(Rstress);

     else

       println("model not implemented ")

     end

     return Rr
end


text:
# AUTO GENERATED FILE - DO NOT EDIT

export 'feffery'_link

"""
    'feffery'_link(;kwargs...)
    'feffery'_link(children::Any;kwargs...)
    'feffery'_link(children_maker::Function;kwargs...)

A Link component.

Keyword arguments:
- `children` (a list of or a singular dash component, string or number; optional): The children of this component
- `id` (String; optional): The ID of this component, used to identify dash components
in callbacks. The ID needs to be unique across all of the
components in an app.
- `className` (String; optional): Often used with CSS to style elements with common properties.
- `disabled` (Bool; optional): If true, clicking on the link does nothing.
- `download` (String; optional)
- `external_link` (Bool; optional): If true, the browser will treat this as an external link,
forcing a page refresh at the new location. If false,
this just changes the location without triggering a page
refresh. Use this if you are observing dcc.Location, for
instance. Defaults to true for absolute URLs and false
otherwise.
- `href` (String; optional): URL of the resource to link to
- `style` (Dict; optional): Defines CSS styles which will override styles previously set.
- `target` (String; optional)
"""
function 'feffery'_link(; kwargs...)
        available_props = Symbol[:children, :id, :className, :disabled, :download, :external_link, :href, :style, :target]
        wild_props = Symbol[]
        return Component("'feffery'_link", "Link", "feffery_antd_components", available_props, wild_props; kwargs...)
end

'feffery'_link(children::Any; kwargs...) = 'feffery'_link(;kwargs..., children = children)
'feffery'_link(children_maker::Function; kwargs...) = 'feffery'_link(children_maker(); kwargs...)

max_stars_repo_name: Beddow/feffery-antd-components

max_issues_repo_name: limmyforget/feffery-antd-components

max_forks_repo_name: limmyforget/feffery-antd-components


text:
# :LN_COBYLA

@testset "f_3p_1im restricted :LN_COBYLA" begin
    method = :CICO_ONE_PASS
    res0 = [get_right_endpoint(
        [3., 8., 2.1],
        i,
        (x::Vector{Float64}) -> f_3p_1im(x) - 9.,
        Val(method);
        scan_bound = 4.,
        local_alg = :LN_COBYLA
    ) for i in 1:3]
    @test res0[1][3] == :SCAN_BOUND_REACHED
    @test res0[2][3] == :SCAN_BOUND_REACHED
    @test res0[3][3] == :SCAN_BOUND_REACHED
end

@testset "f_3p_1im_dep :LN_COBYLA" begin
    method = :CICO_ONE_PASS
    res0 = [get_right_endpoint(
        [3., 2., 2.1],
        i,
        (x::Vector{Float64}) -> f_3p_1im_dep(x) - 9.,
        Val(method);
        local_alg = :LN_COBYLA
    ) for i in 1:3]
    @test isapprox(res0[1][1], 5., atol=1e-2)
    @test res0[1][3] == :BORDER_FOUND_BY_SCAN_TOL
    @test isapprox(res0[2][1], 2.0+2.0*sqrt(2.), atol=1e-2)
    @test res0[2][3] == :BORDER_FOUND_BY_SCAN_TOL
    @test res0[3][3] == :SCAN_BOUND_REACHED
end

@testset "f_3p_1im_dep scan_bound :LN_COBYLA" begin
    method = :CICO_ONE_PASS
    res0 = [get_right_endpoint(
        [3., 2., 2.1],
        i,
        (x::Vector{Float64}) -> f_3p_1im_dep(x) - 9.,
        Val(method);
        scan_bound = [4.,10.,10.][i],
        local_alg = :LN_COBYLA
    ) for i in 1:3]
    @test res0[1][3] == :SCAN_BOUND_REACHED
    @test isapprox(res0[2][1], 2.0+2.0*sqrt(2.), atol=1e-2)
    @test res0[2][3] == :BORDER_FOUND_BY_SCAN_TOL
    @test res0[3][3] == :SCAN_BOUND_REACHED
end

# :LN_PRAXIS
@testset "f_3p_1im restricted :LN_PRAXIS" begin
    method = :CICO_ONE_PASS
    res0 = [get_right_endpoint(
        [3., 8., 2.1],
        i,
        (x::Vector{Float64}) -> f_3p_1im(x) - 9.,
        Val(method);
        scan_bound = 4.,
        local_alg = :LN_PRAXIS
    ) for i in 1:3]
    @test res0[1][3] == :SCAN_BOUND_REACHED
    @test res0[2][3] == :SCAN_BOUND_REACHED
    @test res0[3][3] == :SCAN_BOUND_REACHED
end

@testset "f_3p_1im_dep :LN_PRAXIS" begin
    method = :CICO_ONE_PASS
    res0 = [get_right_endpoint(
        [3., 2., 2.1],
        i,
        (x::Vector{Float64}) -> f_3p_1im_dep(x) - 9.,
        Val(method);
        local_alg = :LN_PRAXIS
    ) for i in 1:3]
    @test isapprox(res0[1][1], 5., atol=1e-2)
    @test res0[1][3] == :BORDER_FOUND_BY_SCAN_TOL
    @test isapprox(res0[2][1], 2.0+2.0*sqrt(2.), atol=1e-2)
    @test res0[2][3] == :BORDER_FOUND_BY_SCAN_TOL
    @test res0[3][3] == :SCAN_BOUND_REACHED
end

@testset "f_3p_1im_dep scan_bound :LN_PRAXIS" begin
    method = :CICO_ONE_PASS
    res0 = [get_right_endpoint(
        [3., 2., 2.1],
        i,
        (x::Vector{Float64}) -> f_3p_1im_dep(x) - 9.,
        Val(method);
        scan_bound = [4.,10.,10.][i],
        local_alg = :LN_PRAXIS
    ) for i in 1:3]
    @test res0[1][3] == :SCAN_BOUND_REACHED
    @test isapprox(res0[2][1], 2.0+2.0*sqrt(2.), atol=1e-2)
    @test res0[2][3] == :BORDER_FOUND_BY_SCAN_TOL
    @test res0[3][3] == :SCAN_BOUND_REACHED
end


text:
include("02_one_site_state_predefined.jl")

println("
#######################################################
# Tutorial 3                                          #
#                                                     #
# 1-site custom state definitions                     #
#######################################################
")

# Customizable:
import ITensors: state

function state(::StateName"iX-", ::SiteType"S=1/2", i::Index)
  iXm = ITensor(i)
  iXm[i => 1] = im / √2
  iXm[i => 2] = -im / √2
  return iXm
end

function state(::StateName"iX-", ::SiteType"S=1/2")
  return [im -im] / √2
end

iXm = state("iX-", i)

@show inner(Zp, iXm)
@show inner(Zm, iXm)