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

using Markdown
using InteractiveUtils

# ╔═╡ a3ef3e3e-81ce-4645-b5a4-1e816803a7fc
begin
	using PlutoUI
end

# ╔═╡ 1c28d260-29e7-401a-b551-eb88bff9b2a7
PlutoUI.TableOfContents(depth=4)

# ╔═╡ 6ab6a977-13ec-412f-b80e-09cd9252624c
md"""
# Material Balances for Single and Multiple Continuous Stirred Tank Reactors (CSTR)
Continuous stirred tank reactors (CSTR) are one of the two most common types of reactors (the other being tubular or plug-flow reactors) used in chemical engineering processes. In this lecture, we'll use our understanding of the material balances (mass and mol) to write down equations that govern the behavior of these reactors.

__Objectives__: at the end of this week(ish), you should be able to:
* Formulate the species mole balances for a single CSTR in which up to ℛ chemical reactions in the bulk and $\mathcal{T}$ biological reactions are occurring in the reactor
* Understand the behavior of a CSTR in terms of the _fractional conversion_ _f_ and time-dependent $\dot{\epsilon}$ of reaction(s)
* Formulate models for the _kinetics_ of chemical reactions
* Formulate the species mole balances for multiple CSTRs in which up to ℛ chemical reactions in the bulk and $\mathcal{T}$ biological reactions are occurring in each reactor

__Assumptions__
* All systems that we consider in the lecture are assumed to be at steady-state
* All liquid phases are assumed to be _ideal_
* All gas phases are assumed to be _ideal_
* All systems that we consider in the lecture are assumed to be _well mixed_

"""

# ╔═╡ 7debf40c-5e61-4ac6-a1d5-4b82927d3dbc
md"""
## Species Mole Balances for a Single CSTR
If we consider a single liquid well-mixed CSTR as our system, then we can use the species mols balances that we have already developed to describe the steady-state behavior of the reactor. The steady-state species mole balance for component $i=1,2,\dots\mathcal{M}$ is given by:

$$\sum_{s=1}^{\mathcal{S}}v_{s}\dot{n}_{is} + \left(\sum_{k=1}^{\mathcal{R}}\sigma_{ik}\hat{r}_{k} + \sum_{j=1}^{\mathcal{T}}\tau_{ij}q_{j}X\right)V = 0$$

where $\dot{n}_{is}$ denotes the flow rate of moles of component _i_ in stream _s_,
$v_{s}$ denotes the direction parameter of stream _s_, and $\mathcal{S}$ denotes the total number of streams.
The second set of summations denotes the reaction terms for both bulk-liquid and possible biological reactions, respectively.
The quantity $\hat{r}_{k}$ denotes the rate per unit volume of chemical reaction _k_ occurring in the bulk fluid, $\tau_{ij}$ denotes the stoichiometric coefficient linking species _i_ with biological reaction _j_, $q_{j}$ denotes the rate per unit cellmass of biological rate _j_ (units: mmol/gDW-hr), and $X$ denotes the cellmass in the reactor (units: gDW/L). Lastly, the symbol $V$ denotes the volume of the _reacting_ fluid in the raector.

"""

# ╔═╡ 148be56c-7926-43b7-b120-f39b252a3380

# ╔═╡ bad7bc52-bece-4d40-aa23-dbc6e268a546
md"""
## Fractional Conversion and Extent
The fractional conversion is a relationship between the number of mol of _reactant_ species _i_ that is entering the reactor (or series of reactors) and the number of moles of species _i_ that are leaving the reactor (or series of reactors). Let's consider a single well-mixed liquid phase CSTR are steady-state, that has a single input and a single output. Then, we can write the fractional conversion of _reactant_ species _i_ as (single in and out consecutively numbered):

$$f_{i} = \frac{\dot{n}_{i,j-1} - \dot{n}_{i,j}}{\dot{n}_{i,j-1}}\qquad \dot{n}_{i,j-1}\neq{0}$$

or after some re-arrangement:

$$\dot{n}_{i,j} = \dot{n}_{i,j-1}\left(1-f_{i}\right)$$

where $\dot{n}_{i,j-1}$ denotes the mol flow rate of species _i_ in-stream $j-1$ (inlet), and $\dot{n}_{i,j}$ denotes the mol flow rate of species _i_ in-stream $j$ (outlet). The fractional conversion $f_{i}$ gives additional information about the chemical reactions that are occurring in the reactor. Alternatively, we could also think about the extent of the reaction.

To understand the relationship between the extent of reaction, and the fractional conversion let's consider a simple example. Suppose we wanted to model a well-mixed liquid CSTR with a single input (s=0) and a single output (s=1) at steady-state.  Further, suppose this CSTR had no biological reactions and a single bulk-phase chemical reaction. In this case, the species mole balance for species _i_ is given by:

$$\dot{n}_{i,0} - \dot{n}_{i,1}+\sigma_{i1}\hat{r}_{1}V = 0$$

Substituting in the definition of fractional conversion of species _i_ and rearranging gives:

$$f_{i}=-\sigma_{i1}\left(\frac{\hat{r}_{1}V}{\dot{n}_{i,0}}\right)\qquad \dot{n}_{i,0}\neq{0}$$

Let's look at the units of the reaction rate term above. The units of $\hat{r}V$ terms are moles/time, or the time-dependent version of the extent of reaction that we have been exploring. Thus, we could re-write the fractional conversion expression (or the species mole balances themselves) as:

$$f_{i}=-\sigma_{i1}\left(\frac{\dot{\epsilon}_{1}}{\dot{n}_{i,0}}\right)\qquad \dot{n}_{i,0}\neq{0}$$

where the dot $\dot{\star}$ on the extent denotes that we are in an open system (and the extent has units of $\star$mol/time).

### Multiple chemical reactions
If there is more than one reaction $\hat{r}_{j}$ where $j=1,2,\dots\mathcal{R}$, then the species mole balance is given by:

$$\dot{n}_{i,0} - \dot{n}_{i,1}+\sum_{j=1}^{\mathcal{R}}\sigma_{ij}\hat{r}_{j}V = 0$$

However, the definition of the fractional conversion remains the same (in - out/in), thus:

$$\dot{n}_{i,1} = \dot{n}_{i,0} + \sum_{j=1}^{\mathcal{R}}\sigma_{ij}\hat{r}_{j}V$$

or after substituting of the fractional conversion, the extent (and rearranging) we get:

$$f_{i}=-\left(\frac{\sum_{j=1}^{\mathcal{R}}\sigma_{ij}\dot{\epsilon_{j}}}{\dot{n}_{i,0}}\right)\qquad \dot{n}_{i,0}\neq{0}$$

where $\hat{r}_{j}V=\dot{\epsilon}_{i}$.

"""

# ╔═╡ 8ea74767-bad8-48ac-a1bf-e612bf6a7e6a
# JV will setup an example in lecture (and then add to the notebook): Degradation of ethanol

# ╔═╡ b7333440-ab75-471d-b932-2c8b8de12706

# ╔═╡ d4b785d8-7871-4993-a0c2-a71dfccf59ad
md"""
## Chemical Reaction Kinetics
The _kinetics_ of a chemical reaction describes the _rate_ at which the reaction proceeds as a function of the conditions in the reactor vessel. Kinetic rate laws have units of $\star$mol/volume-time, and their mathematical form varies significantly with the type of reaction being considered. Let's start by considering the simple non-enzymatic (no catalyst) _reversible_ reaction:

$$A+B\leftrightharpoons{C}$$

A general form for the _net_ rate of this reaction ($\hat{r}_{1}$) is given by:

$$\hat{r}_{1} = k_{1}\prod_{i=1}^{\mathcal{M}}\left[X_{i}\right]^{\alpha_{i1}} - k_{1}^{\prime}\prod_{j=1}^{\mathcal{M}}\left[X_{j}\right]^{\beta_{i1}}$$

where $\left[X_{i}\right]$ denotes the concentration of component $i=1,2,\dots,\mathcal{M}$, and $\alpha_{i1}$ and $\beta_{i1}$ denote the _reaction order_ of component $i$ in reaction $\hat{r}_{1}$. The values of the reation orders $\alpha_{i1}$ and $\beta_{i1}$ depend upon the reaction, and may _not_ always be integer values.
Lastly, the quantities $k_{1}$ and $k_{1}^{\prime}$ denote the rate constant for the forward and reverse directions, respectively. Rate constants have various units depending upon the values of $\alpha_{i1}$
and $\beta_{i1}$.

There is no requirement that $\alpha_{i1}$ and $\beta_{i1}$ be integers (or the stoichiometric coefficients). This is often only true when we have a complete (or simplified) picture of the chemistry that is occurring. In real-life, fractional values for $\alpha_{i1}$ and $\beta_{i1}$ are common in many application areas.

Another way to think about the kinetic rate laws and rate constants is that the overall rate of a reaction is proportional to the concentrations of the species that are participating in the reaction (raised to some power). Given this perspective, the rate constants are then simply constants of proportionality for each direction of the rate. The reaction orders ($\alpha_{i1}$ and $\beta_{i1}$) depend upon our understanding of the chemistry that is occurring, but in a simplified universe we can assume the [Law of Mass Action](https://en.wikipedia.org/wiki/Law_of_mass_action).
"""

# ╔═╡ 8d737835-7442-46a6-bb96-858cce538a77
md"""
### Mass action kinetics

The [law of mass action](https://en.wikipedia.org/wiki/Law_of_mass_action) assumes that the net rate of a chemical reaction is proportional to the concentration of the components raised to the $-{1}\times$ the stoichiometric coefficient of that component in _a particular reaction direction_. For example, for the reaction $A+B\leftrightharpoons{C}$, the mass action rate law would be:

$$\hat{r}_{1} = k_{1}\left[A\right]\left[B\right] - k^{\prime}_{1}\left[C\right]$$

Thus, a general statement of the law of mass action for reaction $j$ (that could involve autocatalysis) is given by:

$$\hat{r}_{j} = k_{j}\prod_{i=1}^{\mathcal{M}}\left[X_{i}\right]^{-\sigma_{ij}} -
k^{\prime}_{j}\prod_{i=1}^{\mathcal{M}}\left[X_{i}\right]^{-\sigma_{ij}}$$

"""

# ╔═╡ 9f8ac34c-9f3b-4247-bd89-7fbb8b555523
md"""
#### Example: Mass-action kinetics

Suppose we had the reaction ([Haber process](https://en.wikipedia.org/wiki/Haber_process)) : $$N_{2}+3H_{2}~{\rightleftharpoons}~2NH_{3}$$

If this reaction followed mass action kinetics, then the net-rate would be:

$$\hat{r}_{1} = k_{1}\left[N_{2}\right]\left[H_{2}\right]^{3} - k^{\prime}_{1}\left[NH_{3}\right]^{2}$$

However, not all chemical reaction rates can be described using mass-action kinetics. For example, consider the production of [Phosgene](https://en.wikipedia.org/wiki/Phosgene): $$CO+Cl_{2}~{\rightleftharpoons}~COCl_{2}$$.

If mass-action kinetics were valid, you would expect the net reaction rate to be given by:

$$\hat{r}_{1} = k_{1}\left[CO\right]\left[Cl_{2}\right] - k^{\prime}_{1}\left[COCl_{2}\right]$$

However, this rate law has been found experimentally to be:

$$\hat{r}_{1} = k_{1}\left[CO\right]\left[Cl_{2}\right]^{3/2} - k^{\prime}_{1}\left[COCl_{2}\right]\left[Cl_{2}\right]^{1/2}$$

Thus, mass-action kinetics may not always be true!
"""

# ╔═╡ fec2cd39-8805-41c3-9ffd-c7dbc901bfb8

# ╔═╡ 21a1f45f-1b5c-406c-b88a-ac3ee194f0b4
md"""

### Temperature dependence of rate constants $k_{i}^{\star}$

The rate constants for some reaction $\hat{r}_{i}$ denoted by $k_{i}$ and $k_{i}^{\prime}$ are functions of temperature in the reactor $T$. One way to model this dependece is:

$$k_{i}^{\star} = A^{\star}_{i}\exp(-\frac{E^{\star}_{i}}{RT})$$

where $A^{\star}_{i}$ denotes a _frequency factor_ (units: variable) for reaction $i$, $E^{\star}_{i}$ denotes the _activation energy_ (units: J/mol) for reaction $i$, and the superscript $\cdot^{\star}$ denotes the reaction direction. This expression, known as the [Arrhenius equation](https://en.wikipedia.org/wiki/Arrhenius_equation), is only one (albeit very commonly used) model of the temperature dependence of rate constants, however, not all reactions obey this expression.

We can estimate the activation energy and the frequency factor from experimental measurements of the rate constants at different temperatures. Rearranging the Arrhenius equation and taking the $\ln\star$ of both sides gives the expression:

$$\ln{k^{\star}_{i}} = \ln{A^{\star}_{i}} - \frac{1}{T}\left(\frac{E^{\star}_{i}}{RT}\right)$$

This expression is of the form $y$=$mx+b$ where $x$ is the inverse temperature, the activation energy term is the slope and the natural log of the frequency factor is the y-intercept.
"""

# ╔═╡ 1bf20268-3bbd-11ec-352b-55a41c839578
html"""
<style>
main {
    max-width: 1200px;
    width: 65%;
    margin: auto;
    font-family: "Roboto, monospace";
}

a {
    color: blue;
    text-decoration: none;
}

.H1 {
    padding: 0px 30px;
}
</style>
<script>
var section = 0;
var subsection = 0;
var headers = document.querySelectorAll('h2, h3, h4');
for (var i=0; i < headers.length; i++) {
    var header = headers[i];
    var text = header.innerText;
    var original = header.getAttribute("text-original");
    if (original === null) {
        // Save original header text
        header.setAttribute("text-original", text);
    } else {
        // Replace with original text before adding section number
        text = header.getAttribute("text-original");
    }
    var numbering = "";
    switch (header.tagName) {
        case 'H2':
            section += 1;
            numbering = section + ".";
            subsection = 0;
            break;
        case 'H3':
            subsection += 1;
            numbering = section + "." + subsection;
            break;
    }
    header.innerText = numbering + " " + text;
};
</script>
"""

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8"

[compat]
PlutoUI = "~0.7.18"
"""

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

[[AbstractPlutoDingetjes]]
deps = ["Pkg"]
git-tree-sha1 = "0ec322186e078db08ea3e7da5b8b2885c099b393"
uuid = "6e696c72-6542-2067-7265-42206c756150"
version = "1.1.0"

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

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

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

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

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

[[Hyperscript]]
deps = ["Test"]
git-tree-sha1 = "8d511d5b81240fc8e6802386302675bdf47737b9"
uuid = "47d2ed2b-36de-50cf-bf87-49c2cf4b8b91"
version = "0.0.4"

[[HypertextLiteral]]
git-tree-sha1 = "5efcf53d798efede8fee5b2c8b09284be359bf24"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
version = "0.9.2"

[[IOCapture]]
deps = ["Logging", "Random"]
git-tree-sha1 = "f7be53659ab06ddc986428d3a9dcc95f6fa6705a"
uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
version = "0.2.2"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

[[PlutoUI]]
deps = ["AbstractPlutoDingetjes", "Base64", "Dates", "Hyperscript", "HypertextLiteral", "IOCapture", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "UUIDs"]
git-tree-sha1 = "57312c7ecad39566319ccf5aa717a20788eb8c1f"
uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8"
version = "0.7.18"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# ╔═╡ Cell order:
# ╟─1c28d260-29e7-401a-b551-eb88bff9b2a7
# ╟─6ab6a977-13ec-412f-b80e-09cd9252624c
# ╟─7debf40c-5e61-4ac6-a1d5-4b82927d3dbc
# ╟─148be56c-7926-43b7-b120-f39b252a3380
# ╟─bad7bc52-bece-4d40-aa23-dbc6e268a546
# ╠═8ea74767-bad8-48ac-a1bf-e612bf6a7e6a
# ╟─b7333440-ab75-471d-b932-2c8b8de12706
# ╟─d4b785d8-7871-4993-a0c2-a71dfccf59ad
# ╟─8d737835-7442-46a6-bb96-858cce538a77
# ╟─9f8ac34c-9f3b-4247-bd89-7fbb8b555523
# ╟─fec2cd39-8805-41c3-9ffd-c7dbc901bfb8
# ╟─21a1f45f-1b5c-406c-b88a-ac3ee194f0b4
# ╠═a3ef3e3e-81ce-4645-b5a4-1e816803a7fc
# ╟─1bf20268-3bbd-11ec-352b-55a41c839578
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
using CPIDataBase
using Documenter

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

makedocs(;
    modules=[CPIDataBase],
    authors="Rodrigo Chang and DIE-BG collaborators",
    repo="https://github.com/DIE-BG/CPIDataBase.jl/blob/{commit}{path}#{line}",
    sitename="CPIDataBase.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://die-bg.github.io/CPIDataBase.jl",
        assets=String[],
    ),
    # format=Documenter.LaTeX(),
    pages=[
        "Introducción" => "index.md",
        "Estructura jerárquica del IPC" => "CPITrees.md",
        "API" => "API.md",
        "TestHelpers API" => "TestHelpers.md",
    ],
)

deploydocs(;
    repo="github.com/DIE-BG/CPIDataBase.jl",
    devbranch="main",
)

ext: jl


text:
export Hostlist

"""
    Hostlist(node_list)

Takes a slurm hostlist of form `"node[1-3,6]"` and provides an iterator
that gives the full hostnames `["node1", "node2", "node3", "node6"]`.

Note: You can only iterate through a hostlist once.

# Usage
```julia
hostlist = Hostname("node[1-3,6]")
for host in hostlist
  @show host
end
hostlist = Hostname("node[1-5,7,9-16]")
collect(hostlist)
```
"""
type Hostlist
  hlist :: api.hostlist_t

  function Hostlist(node_list :: String)
    slurm_hl = api.slurm_hostlist_create(node_list)
    if slurm_hl == C_NULL
      error("Could not allocate memory for hostlist.")
    end
    hl = new(slurm_hl)
    finalizer(hl, delete)
    return hl
  end
end

function delete(hl :: Hostlist)
  api.slurm_hostlist_destroy(hl.hlist)
end

shift(hl :: Hostlist) = api.slurm_hostlist_shift(hl.hlist)
Base.start(hl :: Hostlist) = shift(hl)
Base.done(::Hostlist, state) = state == C_NULL
Base.next(hl:: Hostlist, state) = unsafe_string(state), shift(hl)
Base.eltype(::Hostlist) = String
Base.iteratorsize(::Type{Hostlist}) = Base.SizeUnknown()


text:
"""
Callback-based algorithm for GBD in a ground structure, with discrete diameter
choice in master.

Solver object to store parameters.
"""
struct CallbackGBD <: GroundStructureSolver
    mastersolver
    subsolver
    timelimit::Float64 # seconds
    writemodels::Bool
    addcritpath::Bool
    addnogoods::Bool

    function CallbackGBD(mastersolver, subsolver;
                         timelimit=Inf, writemodels=false,
                         addcritpath=true, addnogoods=false)
        new(mastersolver, subsolver, timelimit, writemodels,
            addcritpath, addnogoods)
    end
end

"GBD on ground structure with callbacks"
function PipeLayout.optimize(inst::Instance, topo::Topology,
                             solver::CallbackGBD)
    # initialization
    finaltime = time() + solver.timelimit

    # no solution yet
    bestsol = nothing
    primal = Inf

    # use master problem from IterGBD algorithm
    master = Master(make_master(inst, topo, solver.mastersolver)...)
    solver.writemodels && writeLP(master.model, "master.lp", genericnames=false)

    # get access to SCIP.Optimizer instance (not factory)
    scip::SCIP.Optimizer = JuMP.backend(master.model)

    # enforce tree topology with constraint handler (higher prio)
    treetopohdlr = TreeTopoHdlr(scip)
    SCIP.include_conshdlr(
        scip, treetopohdlr;
        needs_constraints=true, enforce_priority=-15, check_priority=-7_000_000)
    SCIP.add_constraint(scip, treetopohdlr, TreeTopoCons(topo, master.y))

    # enforce subproblem with constraint handler (lower prio)
    gbdsubhdlr = GBDSubHdlr(scip, solver.subsolver, finaltime,
                            solver.addnogoods, solver.addcritpath)
    SCIP.include_conshdlr(
        scip, gbdsubhdlr;
        needs_constraints=true, enforce_priority=-16, check_priority=-7_100_000)
    SCIP.add_constraint(scip, gbdsubhdlr, GBDSubCons(inst, topo, master))

    # solve master problem (has callback)
    JuMP.optimize!(master.model)
    status = JuMP.termination_status(master.model)

    # TODO: correct bound?
    dual_bound = JuMP.objective_bound(master.model)
    # TODO: extract nnodes?
    nnodes = -1
    Result(status, gbdsubhdlr.best_solution, gbdsubhdlr.primal_bound,
           dual_bound, nnodes)
end


text:
using FranklinTemplates, Franklin

descr = Dict{String,String}(
    "sandbox"   => """
                   sandbox

Simplest one-page layout, meant for practicing or testing Franklin syntax.

                   """,
    "sandbox-extended"   => """
                   sandbox-extended

Simplest one-page layout, meant for practising interaction between Franklin and other packages.

                   """,
    "basic"     => """
                   basic

Barebone responsive theme with a top navigation bar, no extra javascript and a simple stylesheet.

                   """,
    "jemdoc"    => """
                   jemdoc

Simple theme with a side navigation bar, no extra javascript and a simple stylesheet. (Adapted from the original Jemdoc theme.)

                   """,
    "just-the-docs" => """
                   just-the-docs

Simple documentation theme with a side navigation bar, and no extra javascript (Adapted from the Jekyll theme.)

                   """,
    "hyde"      => """
                   hyde

A neat two-column responsive theme with a side navigation bar, no extra javascript and a simple stylesheet. (Adapted from the Jekyll theme.)

                   """,
    "hypertext" => """
                   hypertext

Barebone responsive theme with a simple top navigation bar, no extra javascript and a simple stylesheet. (Adapted from the Grav theme.)

                   """,
    "lanyon"    => """
                   lanyon

A neat single-column theme with a sliding menu-bar, no extra javascript and a simple stylesheet. (Adapted from the Jekyll theme.)

                   """,
    "minimal-mistakes" => """
                   minimal-mistakes

A responsive two-column theme with a nice landing page, extra javascript for the responsiveness. (Adapted from the Jekyll theme.)

                   """,
    "pure-sm"   => """
                   pure-sm

Single-column theme with a sliding menu-bar, a simple stylesheet and some javascript for the menu bar. (Adapted from the Pure CSS theme.)

                   """,
    "tufte"     => """
                   tufte

A neat single-column theme adapted from tufte.css with a focus on clarity and nice typesetting, no extra javascript and a sophisticated stylesheet.

                   """,
    "vela"      => """
                   vela

A single-column theme with a sliding menu-bar, a simple stylesheet and extra javascript for the menu-bar. (Adapted from the Grav theme.)

                   """,
    )

build = joinpath(@__DIR__, "build")

isdir(build) || mkdir(build)

function fixdir(τ::String)
    for name in readdir(τ; join=true)
        occursin("__site", name) && continue
        rm(name, recursive=true)
    end
    for name in readdir(joinpath(τ, "__site"); join=true)
        cp(name, replace(name, "__site" => ""))
    end
    rm(joinpath(τ, "__site"), recursive=true)
    # 2. fix links in index.html etc
    html_files = String[]
    for (root, _, files) ∈ walkdir(τ)
        for file ∈ files
            endswith(file, ".html") || continue
            fp   = joinpath(root, file)
            html = read(fp, String)
            html = replace(html, "href=\"/" => "href=\"/templates/$τ/")
            html = replace(html, "src=\"/" => "src=\"/templates/$τ/")
            write(fp, html)
        end
    end
    return
end

# make a template folder with a subfolder for each template
# compile each template with a fullpass of Franklin
begin
    # Clean up the directory to avoid clashes etc.
    if isdir(joinpath(build, "templates"))
        rm(joinpath(build, "templates"), recursive=true)
    end
    # Make the template folder.
    templates = mkpath(joinpath(build, "templates"))
    cd(templates)
    for τ ∈ FranklinTemplates.LIST_OF_TEMPLATES
        println("🍏  template: $τ")
        FranklinTemplates.newsite(τ; template=τ, changedir=true, verbose=false)
        optimize(minify=(τ ∉ ("vela", "sandbox-extended"))) # see issue #7
        cd("..")
        fixdir(τ)
    end
    # copy over the thumb folder
    cp(joinpath(dirname(build), "thumb"), joinpath(build, "thumb"), force=true)
end

# build the index page
begin
    html = IOBuffer()
    write(html, read(joinpath(@__DIR__, "index_head.html"), String))

    # One card per template
    for τ ∈ FranklinTemplates.LIST_OF_TEMPLATES
        c = """

              $(descr[τ])

            """
        write(html, c)
    end
    write(html, read(joinpath(@__DIR__, "index_foot.html"), String))
    write(joinpath(build, "index.html"), take!(html))
end

cd(pkgdir(FranklinTemplates))


text:
include("Include.jl")

function objective_function(parameter_guess_array,time_start,time_step_size,time_stop,model_data_dictionary,exp_data_dictionary)

    # what is the host_type?
    host_type = :cell_free

    # Phase 1: parameter update =========================================================================== #
    # update the paramaters in the model data dictionary -
    # for now - lets only search over dG's -
    R = model_data_dictionary["R"]
    T_K = model_data_dictionary["T_K"]

    # compute W -
    tmp_W_array = Float64[]
    for index = 1:2
        parameter_guess = parameter_guess_array[index]
        value = exp(-1*(parameter_guess/100)/(R*T_K))
        push!(tmp_W_array,value)
    end

    # update the control W's -
    control_parameter_dictionary = model_data_dictionary["control_parameter_dictionary"]
	control_parameter_dictionary["W_deGFP_RNAP"] = tmp_W_array[1]       # 3
	control_parameter_dictionary["W_deGFP_sigma_70"] = tmp_W_array[2]   # 4
    model_data_dictionary["control_parameter_dictionary"] = control_parameter_dictionary

    binding_parameter_dictionary = model_data_dictionary["binding_parameter_dictionary"]
	binding_parameter_dictionary["n_deGFP_sigma_70"] = parameter_guess_array[3]
	binding_parameter_dictionary["K_deGFP_sigma_70"] = parameter_guess_array[4]
    model_data_dictionary["binding_parameter_dictionary"] = binding_parameter_dictionary

    # time constant modifier -
    # time constant modifiers -
	time_constant_modifier_array = [
		0.0	                        ;	# 1	deGFP
		0.0	                        ;	# 2	sigma_70
		parameter_guess_array[5] 	;	# 3	mRNA_deGFP
		1.0	                        ;	# 4	mRNA_sigma_70
		parameter_guess_array[6] 	;	# 5	protein_deGFP
		1.0	                        ;	# 6	protein_sigma_70
    ]
    model_data_dictionary["time_constant_modifier_array"] = time_constant_modifier_array

    # setup degradation_modifier_array -
    degradation_modifier_array = [
		0.0	;	# 1	deGFP
		0.0	;	# 2	sigma_70
		parameter_guess_array[7]	;	# 3	mRNA_deGFP
		1.0	;	# 4	mRNA_sigma_70
		parameter_guess_array[8]	;	# 5	protein_deGFP
		parameter_guess_array[9]	;	# 6	protein_sigma_70
    ]

    # update the translation time -
    model_data_dictionary["half_life_translation_capacity"] = parameter_guess_array[10]

    # lastly, update KL -
    biophysical_constants_dictionary = model_data_dictionary["biophysical_constants_dictionary"]
    biophysical_constants_dictionary["translation_saturation_constant"] = parameter_guess_array[11]
    model_data_dictionary["biophysical_constants_dictionary"] = biophysical_constants_dictionary

    # grab defaults -
    species_symbol_type_array = model_data_dictionary["species_symbol_type_array"]
    protein_coding_length_array = model_data_dictionary["protein_coding_length_array"]
    gene_coding_length_array = model_data_dictionary["gene_coding_length_array"]
    time_constant_modifier_array = model_data_dictionary["time_constant_modifier_array"]
    initial_condition_array = model_data_dictionary["initial_condition_array"]

    # # get gene IC -
    idx_gene = findall(x->x==:gene,species_symbol_type_array)
    gene_abundance_array = initial_condition_array[idx_gene]

    # Precompute the translation parameters -
	translation_parameter_array = precompute_translation_parameter_array(biophysical_constants_dictionary, protein_coding_length_array, time_constant_modifier_array,host_type)
    model_data_dictionary["translation_parameter_array"] = translation_parameter_array

	# Precompute the kinetic limit of transcription -
	transcription_kinetic_limit_array = precompute_transcription_kinetic_limit_array(biophysical_constants_dictionary, gene_coding_length_array, gene_abundance_array, time_constant_modifier_array, host_type)
    model_data_dictionary["transcription_kinetic_limit_array"] = transcription_kinetic_limit_array

    # Dilution degrdation matrix -
    dilution_degradation_matrix = build_dilution_degradation_matrix(biophysical_constants_dictionary, species_symbol_type_array, degradation_modifier_array)
    model_data_dictionary["dilution_degradation_matrix"] = dilution_degradation_matrix
    # ===================================================================================================== #

    # Phase 2:  solve model equations ===================================================================== #
    # solve the balance equations -
    (TSIM,XSIM) = SolveBalances(time_start,time_stop,time_step_size,model_data_dictionary)
    # ===================================================================================================== #

    # Phase 3:  compute simulation error ================================================================== #
    # compute the error - we need to do a bunch of interpolation -
    tsim_exp = exp_data_dictionary["mRNA_data_array"][:,1]

    # GFP mRNA -
    itp_gfp_mRNA =  LinearInterpolation(TSIM, (1000)*XSIM[:,3]);
    mRNA_GFP_sim = itp_gfp_mRNA[tsim_exp]  # convert to muM from nM

    # GFP protein -
    itp_gfp_protein =  LinearInterpolation(TSIM, XSIM[:,5]);
    protein_GFP_sim = itp_gfp_protein[tsim_exp]

    # get experimental data -
    mRNA_GFP_exp = exp_data_dictionary["mRNA_data_array"][:,2]          # mean is col 2 nM
    mRNA_GFP_std_exp = exp_data_dictionary["mRNA_data_array"][:,3]      # stdev is col 3 nM

    protein_GFP_exp = exp_data_dictionary["prot_data_array"][:,2]       # mean is col 2 muM
    protein_GFP_std_exp = exp_data_dictionary["prot_data_array"][:,3]   # stdev is col 3 muM

    # compute error terms -
    error_term_array = zeros(2,1)

    # mRNA GFP -
    #mRNA_GFP_std_exp[1] = 1.0   # we have 0 ic
    #tmp_arr = 1.0./((mRNA_GFP_std_exp).^2)
    #W_mRNA = diagm(tmp_arr)
    error_vector_1 = (mRNA_GFP_exp .- mRNA_GFP_sim)
    error_term_array[1] = transpose(error_vector_1)*error_vector_1

    # protein deGFP -
    #protein_GFP_std_exp[1] = 1.0
    #tmp_arr = 1.0./((protein_GFP_std_exp).^2)
    #W_prot = diagm(tmp_arr)
    error_vector_2 = (protein_GFP_exp .- protein_GFP_sim)
    error_term_array[2] = transpose(error_vector_2)*error_vector_2
    # ===================================================================================================== #

    # return -
    return error_term_array
end

# Evaluates the objective function values -
function local_refienment_step(path_to_data_dir, parameter_array; sigma=0.05, iteration_max=100)

    # inner functions -
    function _compute_error_total(objective_array,W)
        value = transpose(objective_array)*W*objective_array
        return value[1]
    end

    # initialize -
    number_of_parameters = length(parameter_array)
    BIG = 1e10

    # load the default data_dictionary -
    time_start = 0.0
    time_stop = 16.0
    time_step_size = 0.01

    # what is the host_type?
    host_type = :cell_free

    # path to parameters -
    path_to_biophysical_constants_file = "./CellFree.json"

    # wght array -
    W = diagm(ones(2))

    # Load the data dictionary (uses the default biophysical_constants file)
    default_data_dictionary = build_data_dictionary((time_start,time_stop,time_step_size), path_to_biophysical_constants_file, host_type)

    # Set some values for the weights, gene lengths etc -
    model_data_dictionary = customize_data_dictionary(default_data_dictionary,host_type)

    # load the experimental data -
    exp_data_dictionary = load_experimental_data_dictionary(path_to_data_dir)

    # setup the functions -
    OF(P) = objective_function(P,time_start,time_step_size,time_stop,model_data_dictionary,exp_data_dictionary)

    # calculate the starting error -
    parameter_array_best = parameter_array
    error_array = BIG*ones(4)
    error_array[1] = _compute_error_total(OF(parameter_array_best), W)

    # main refinement loop -
    iteration_counter = 1
    while (iteration_counter<iteration_max)

        # take a step up -
        parameter_up = parameter_array_best.*(1 .+ sigma*rand(number_of_parameters))
        parameter_up = check_parameter_bounds(parameter_up)

        # take a step down -
        parameter_down = parameter_array_best.*(1 .- sigma*rand(number_of_parameters))
        parameter_down = check_parameter_bounds(parameter_down)

        # Evaluate the obj function -
        error_array[2] = _compute_error_total(OF(parameter_up),W)
        error_array[3] = _compute_error_total(OF(parameter_down),W)

        # Calculate a correction factor -
        a = error_array[2]+error_array[3] - 2.0*error_array[1]
        parameter_corrected = parameter_array_best
        if (a>0.0)
            amda = -0.5*(error_array[3] - error_array[2])/a
            parameter_corrected = parameter_array_best .+ amda*rand(number_of_parameters)
            parameter_corrected = check_parameter_bounds(parameter_corrected)
            error_array[4] = _compute_error_total(OF(parameter_corrected), W)
        end

        # Which step has the min error?
        min_index = argmin(error_array)
        if (min_index == 1)
            parameter_array_best = parameter_array_best
        elseif (min_index == 2)
            parameter_array_best = parameter_up
        elseif (min_index == 3)
            parameter_array_best = parameter_down
        elseif (min_index == 4)
            parameter_array_best = parameter_corrected
        end

        # Update the local error
        error_array[1] = error_array[min_index]

        @show iteration_counter,error_array[min_index]

        # update local counter -
        iteration_counter = iteration_counter + 1
    end

    return parameter_array_best
end

function check_parameter_bounds(parameter_array)

    # setup paramter bounds -
    pvec_bounds = [

        # dG's -
        20000.0  80000.0    ;   # 1     W_deGFP_RNAP
        -50000.0  -100.0    ;   # 2     W_deGFP_sigma_70

        # binding parameters -
        0.5 10.0            ;   # 3     n_deGFP_sigma_70
        0.001 100.0         ;   # 4     K_deGFP_sigma_70

        # time constants -
		0.001 100.0         ;	# 5	    mRNA_deGFP
		0.001 100.0         ;	# 6	    protein_deGFP

        # degradation mods -
		0.001 100.0 	    ;	# 7	    mRNA_deGFP
		0.001 100.0 	    ;	# 8	    protein_deGFP
        0.001 100.0 	    ;	# 9	    protein_sigma_70

         # w -
         4.0 10.0           ;   # 10    translation capacity half-life

        # KL value -
        100.0 500.0         ;   # 11    KL in muM
    ];

    # tmp -
    pvec_initial = parameter_array

    # check bounds -
    number_of_parameters = length(pvec_initial)
    for parameter_index = 1:number_of_parameters

        # what is the parameter value?
        p_i = pvec_initial[parameter_index]

        # is p_i outside of the bounds?
        lb_value = pvec_bounds[parameter_index,1]
        ub_value = pvec_bounds[parameter_index,2]

        if (p_i<lb_value)
            pvec_initial[parameter_index,1] = lb_value
        end

        if (p_i>ub_value)
            pvec_initial[parameter_index,1] = ub_value
        end
    end

    # return -
    return pvec_initial
end

function neighbor_function(parameter_array; sigma=0.05)

    # setup -
    number_of_parameters = length(parameter_array)

    # calculate new parameter array -
    new_parameter_array = parameter_array.*(1 .+ sigma*randn(number_of_parameters))

    # check the bounds and return -
    return check_parameter_bounds(new_parameter_array)
end

function cooling_function(temperature)

  # define my new temperature -
  alpha = 0.9
  return alpha*temperature
end

function acceptance_probability_function(rank_array,temperature)
    return (exp(-rank_array[end]/temperature))
end

function main(path_to_data_dir::String, initial_parameter_array::Array{Float64,1}; rank_cutoff::Int64=4, maximum_number_of_iterations::Int64=100)

    # load the default data_dictionary -
    time_start = 0.0
    time_stop = 16.0
    time_step_size = 0.01

    # what is the host_type?
    host_type = :cell_free
    number_of_parameters = length(initial_parameter_array)

    # path to parameters -
    path_to_biophysical_constants_file = "./CellFree.json"

    # Load the data dictionary (uses the default biophysical_constants file)
    default_data_dictionary = build_data_dictionary((time_start,time_stop,time_step_size), path_to_biophysical_constants_file, host_type)

    # Set some values for the weights, gene lengths etc -
    model_data_dictionary = customize_data_dictionary(default_data_dictionary,host_type)

    # load the experimental data -
    exp_data_dictionary = load_experimental_data_dictionary(path_to_data_dir)

    # setup the functions -
    OF(P) = objective_function(P,time_start,time_step_size,time_stop,model_data_dictionary,exp_data_dictionary)
    NF(P) = neighbor_function(P;sigma=0.01)

    # make call to POETs -
    (EC,PC,RA) = estimate_ensemble(OF,NF,acceptance_probability_function,cooling_function,initial_parameter_array;rank_cutoff=rank_cutoff,maximum_number_of_iterations=maximum_number_of_iterations)

    # return -
    return (EC,PC,RA)
end

 # setup initial condition vector -
 pvec_initial = [

    # dG's -
    40000.0     ;   # 1     W_deGFP_RNAP
    -25000.0    ;   # 2     W_deGFP_sigma_70

    # binding parameters -
    1.0         ;   # 3     n_deGFP_sigma_70
    30.0        ;   # 4     K_deGFP_sigma_70

    # time constants -
    1.0         ;	# 5	    mRNA_deGFP
    1.0         ;	# 6	    protein_deGFP

    # degradation mods -
    1.0 	    ;	# 7	    mRNA_deGFP
    1.0 	    ;	# 8	    protein_deGFP
    1.0 	    ;	# 9	    protein_sigma_70

    # w -
    8.0         ;   # 10    translation capacity half-life

    # KL -
    250.0       ;   # 11    KL in muM
];

# setup -
path_to_data_dir = "$(pwd())/data"
pV = neighbor_function(pvec_initial; sigma=0.25)
EC = 0
PC = 0
RA = 0

# execute -
number_of_trials = 20
for trial_index = 1:number_of_trials

    global pV
    global EC
    global PC
    global RA

   # do a local step -
    if (mod(trial_index,2) == 0)

        # find the lowest score pV -
        sum_error_array = sum(EC,dims=1)
        best_p_index = argmin(vec(sum_error_array))
        pV_best = PC[:,best_p_index]

        # local refine -
        pV = local_refienment_step(path_to_data_dir, pV_best; iteration_max=500)
    end

    # main -
    (EC,PC,RA) = main(path_to_data_dir, vec(pV); rank_cutoff=3,maximum_number_of_iterations=100)

    # dump results to disk -
    fname = "./poets_ensemble/RA_T$(trial_index).dat"
    writedlm(fname,RA)
    fname = "./poets_ensemble/EC_T$(trial_index).dat"
    writedlm(fname,EC)
    fname = "./poets_ensemble/PC_T$(trial_index).dat"
    writedlm(fname,PC)
end

max_stars_repo_name: varnerlab/Biophysical-TXTL-Model-Code

max_issues_repo_name: varnerlab/Biophysical-TXTL-Model-Code

max_forks_repo_name: varnerlab/Biophysical-TXTL-Model-Code


text:
# generated
# length(dict) = 699
const emoji_symbols = Dict{String, String}(
    "\\:a:" => "🅰",
    "\\:admission_tickets:" => "🎟",
    "\\:airplane:" => "✈",
    "\\:alembic:" => "⚗",
    "\\:arrow_backward:" => "◀",
    "\\:arrow_down:" => "⬇",
    "\\:arrow_forward:" => "▶",
    "\\:arrow_heading_down:" => "⤵",
    "\\:arrow_heading_up:" => "⤴",
    "\\:arrow_left:" => "⬅",
    "\\:arrow_lower_left:" => "↙",
    "\\:arrow_lower_right:" => "↘",
    "\\:arrow_right:" => "➡",
    "\\:arrow_right_hook:" => "↪",
    "\\:arrow_up:" => "⬆",
    "\\:arrow_up_down:" => "↕",
    "\\:arrow_upper_left:" => "↖",
    "\\:arrow_upper_right:" => "↗",
    "\\:artist:" => "🧑\u200d🎨",
    "\\:astronaut:" => "🧑\u200d🚀",
    "\\:atom_symbol:" => "⚛",
    "\\:b:" => "🅱",
    "\\:bald_man:" => "👨\u200d🦲",
    "\\:bald_person:" => "🧑\u200d🦲",
    "\\:bald_woman:" => "👩\u200d🦲",
    "\\:ballot_box_with_ballot:" => "🗳",
    "\\:ballot_box_with_check:" => "☑",
    "\\:bangbang:" => "‼",
    "\\:barely_sunny:" => "🌥",
    "\\:beach_with_umbrella:" => "🏖",
    "\\:bed:" => "🛏",
    "\\:bellhop_bell:" => "🛎",
    "\\:biohazard_sign:" => "☣",
    "\\:black_cat:" => "🐈\u200d⬛",
    "\\:black_circle_for_record:" => "⏺",
    "\\:black_left_pointing_double_triangle_with_vertical_bar:" => "⏮",
    "\\:black_medium_square:" => "◼",
    "\\:black_nib:" => "✒",
    "\\:black_right_pointing_double_triangle_with_vertical_bar:" => "⏭",
    "\\:black_right_pointing_triangle_with_double_vertical_bar:" => "⏯",
    "\\:black_small_square:" => "▪",
    "\\:black_square_for_stop:" => "⏹",
    "\\:blond-haired-man:" => "👱\u200d♂",
    "\\:blond-haired-woman:" => "👱\u200d♀",
    "\\:building_construction:" => "🏗",
    "\\:camping:" => "🏕",
    "\\:candle:" => "🕯",
    "\\:card_file_box:" => "🗃",
    "\\:card_index_dividers:" => "🗂",
    "\\:chains:" => "⛓",
    "\\:chess_pawn:" => "♟",
    "\\:chipmunk:" => "🐿",
    "\\:cityscape:" => "🏙",
    "\\:classical_building:" => "🏛",
    "\\:cloud:" => "☁",
    "\\:clubs:" => "♣",
    "\\:cn:" => "🇨🇳",
    "\\:coffin:" => "⚰",
    "\\:comet:" => "☄",
    "\\:compression:" => "🗜",
    "\\:congratulations:" => "㊗",
    "\\:control_knobs:" => "🎛",
    "\\:cook:" => "🧑\u200d🍳",
    "\\:copyright:" => "©",
    "\\:couch_and_lamp:" => "🛋",
    "\\:crossed_swords:" => "⚔",
    "\\:curly_haired_man:" => "👨\u200d🦱",
    "\\:curly_haired_person:" => "🧑\u200d🦱",
    "\\:curly_haired_woman:" => "👩\u200d🦱",
    "\\:dagger_knife:" => "🗡",
    "\\:dark_sunglasses:" => "🕶",
    "\\:de:" => "🇩🇪",
    "\\:deaf_man:" => "🧏\u200d♂",
    "\\:deaf_woman:" => "🧏\u200d♀",
    "\\:derelict_house_building:" => "🏚",
    "\\:desert:" => "🏜",
    "\\:desert_island:" => "🏝",
    "\\:desktop_computer:" => "🖥",
    "\\:diamonds:" => "♦",
    "\\:double_vertical_bar:" => "⏸",
    "\\:dove_of_peace:" => "🕊",
    "\\:eight:" => "8⃣",
    "\\:eight_pointed_black_star:" => "✴",
    "\\:eight_spoked_asterisk:" => "✳",
    "\\:eject:" => "⏏",
    "\\:email:" => "✉",
    "\\:es:" => "🇪🇸",
    "\\:eye-in-speech-bubble:" => "👁\u200d🗨",
    "\\:eye:" => "👁",
    "\\:face_exhaling:" => "😮\u200d💨",
    "\\:face_in_clouds:" => "😶\u200d🌫",
    "\\:face_with_spiral_eyes:" => "😵\u200d💫",
    "\\:factory_worker:" => "🧑\u200d🏭",
    "\\:farmer:" => "🧑\u200d🌾",
    "\\:female-artist:" => "👩\u200d🎨",
    "\\:female-astronaut:" => "👩\u200d🚀",
    "\\:female-construction-worker:" => "👷\u200d♀",
    "\\:female-cook:" => "👩\u200d🍳",
    "\\:female-detective:" => "🕵\u200d♀",
    "\\:female-doctor:" => "👩\u200d⚕",
    "\\:female-factory-worker:" => "👩\u200d🏭",
    "\\:female-farmer:" => "👩\u200d🌾",
    "\\:female-firefighter:" => "👩\u200d🚒",
    "\\:female-guard:" => "💂\u200d♀",
    "\\:female-judge:" => "👩\u200d⚖",
    "\\:female-mechanic:" => "👩\u200d🔧",
    "\\:female-office-worker:" => "👩\u200d💼",
    "\\:female-pilot:" => "👩\u200d✈",
    "\\:female-police-officer:" => "👮\u200d♀",
    "\\:female-scientist:" => "👩\u200d🔬",
    "\\:female-singer:" => "👩\u200d🎤",
    "\\:female-student:" => "👩\u200d🎓",
    "\\:female-teacher:" => "👩\u200d🏫",
    "\\:female-technologist:" => "👩\u200d💻",
    "\\:female_elf:" => "🧝\u200d♀",
    "\\:female_fairy:" => "🧚\u200d♀",
    "\\:female_genie:" => "🧞\u200d♀",
    "\\:female_mage:" => "🧙\u200d♀",
    "\\:female_sign:" => "♀",
    "\\:female_superhero:" => "🦸\u200d♀",
    "\\:female_supervillain:" => "🦹\u200d♀",
    "\\:female_vampire:" => "🧛\u200d♀",
    "\\:female_zombie:" => "🧟\u200d♀",
    "\\:ferry:" => "⛴",
    "\\:file_cabinet:" => "🗄",
    "\\:film_frames:" => "🎞",
    "\\:film_projector:" => "📽",
    "\\:firefighter:" => "🧑\u200d🚒",
    "\\:five:" => "5⃣",
    "\\:flag-ac:" => "🇦🇨",
    "\\:flag-ad:" => "🇦🇩",
    "\\:flag-ae:" => "🇦🇪",
    "\\:flag-af:" => "🇦🇫",
    "\\:flag-ag:" => "🇦🇬",
    "\\:flag-ai:" => "🇦🇮",
    "\\:flag-al:" => "🇦🇱",
    "\\:flag-am:" => "🇦🇲",
    "\\:flag-ao:" => "🇦🇴",
    "\\:flag-aq:" => "🇦🇶",
    "\\:flag-ar:" => "🇦🇷",
    "\\:flag-as:" => "🇦🇸",
    "\\:flag-at:" => "🇦🇹",
    "\\:flag-au:" => "🇦🇺",
    "\\:flag-aw:" => "🇦🇼",
    "\\:flag-ax:" => "🇦🇽",
    "\\:flag-az:" => "🇦🇿",
    "\\:flag-ba:" => "🇧🇦",
    "\\:flag-bb:" => "🇧🇧",
    "\\:flag-bd:" => "🇧🇩",
    "\\:flag-be:" => "🇧🇪",
    "\\:flag-bf:" => "🇧🇫",
    "\\:flag-bg:" => "🇧🇬",
    "\\:flag-bh:" => "🇧🇭",
    "\\:flag-bi:" => "🇧🇮",
    "\\:flag-bj:" => "🇧🇯",
    "\\:flag-bl:" => "🇧🇱",
    "\\:flag-bm:" => "🇧🇲",
    "\\:flag-bn:" => "🇧🇳",
    "\\:flag-bo:" => "🇧🇴",
    "\\:flag-bq:" => "🇧🇶",
    "\\:flag-br:" => "🇧🇷",
    "\\:flag-bs:" => "🇧🇸",
    "\\:flag-bt:" => "🇧🇹",
    "\\:flag-bv:" => "🇧🇻",
    "\\:flag-bw:" => "🇧🇼",
    "\\:flag-by:" => "🇧🇾",
    "\\:flag-bz:" => "🇧🇿",
    "\\:flag-ca:" => "🇨🇦",
    "\\:flag-cc:" => "🇨🇨",
    "\\:flag-cd:" => "🇨🇩",
    "\\:flag-cf:" => "🇨🇫",
    "\\:flag-cg:" => "🇨🇬",
    "\\:flag-ch:" => "🇨🇭",
    "\\:flag-ci:" => "🇨🇮",
    "\\:flag-ck:" => "🇨🇰",
    "\\:flag-cl:" => "🇨🇱",
    "\\:flag-cm:" => "🇨🇲",
    "\\:flag-co:" => "🇨🇴",
    "\\:flag-cp:" => "🇨🇵",
    "\\:flag-cr:" => "🇨🇷",
    "\\:flag-cu:" => "🇨🇺",
    "\\:flag-cv:" => "🇨🇻",
    "\\:flag-cw:" => "🇨🇼",
    "\\:flag-cx:" => "🇨🇽",
    "\\:flag-cy:" => "🇨🇾",
    "\\:flag-cz:" => "🇨🇿",
    "\\:flag-dg:" => "🇩🇬",
    "\\:flag-dj:" => "🇩🇯",
    "\\:flag-dk:" => "🇩🇰",
    "\\:flag-dm:" => "🇩🇲",
    "\\:flag-do:" => "🇩🇴",
    "\\:flag-dz:" => "🇩🇿",
    "\\:flag-ea:" => "🇪🇦",
    "\\:flag-ec:" => "🇪🇨",
    "\\:flag-ee:" => "🇪🇪",
    "\\:flag-eg:" => "🇪🇬",
    "\\:flag-eh:" => "🇪🇭",
    "\\:flag-england:" => "🏴\Ue0067\Ue0062\Ue0065\Ue006e\Ue0067\Ue007f",
    "\\:flag-er:" => "🇪🇷",
    "\\:flag-et:" => "🇪🇹",
    "\\:flag-eu:" => "🇪🇺",
    "\\:flag-fi:" => "🇫🇮",
    "\\:flag-fj:" => "🇫🇯",
    "\\:flag-fk:" => "🇫🇰",
    "\\:flag-fm:" => "🇫🇲",
    "\\:flag-fo:" => "🇫🇴",
    "\\:flag-ga:" => "🇬🇦",
    "\\:flag-gd:" => "🇬🇩",
    "\\:flag-ge:" => "🇬🇪",
    "\\:flag-gf:" => "🇬🇫",
    "\\:flag-gg:" => "🇬🇬",
    "\\:flag-gh:" => "🇬🇭",
    "\\:flag-gi:" => "🇬🇮",
    "\\:flag-gl:" => "🇬🇱",
    "\\:flag-gm:" => "🇬🇲",
    "\\:flag-gn:" => "🇬🇳",
    "\\:flag-gp:" => "🇬🇵",
    "\\:flag-gq:" => "🇬🇶",
    "\\:flag-gr:" => "🇬🇷",
    "\\:flag-gs:" => "🇬🇸",
    "\\:flag-gt:" => "🇬🇹",
    "\\:flag-gu:" => "🇬🇺",
    "\\:flag-gw:" => "🇬🇼",
    "\\:flag-gy:" => "🇬🇾",
    "\\:flag-hk:" => "🇭🇰",
    "\\:flag-hm:" => "🇭🇲",
    "\\:flag-hn:" => "🇭🇳",
    "\\:flag-hr:" => "🇭🇷",
    "\\:flag-ht:" => "🇭🇹",
    "\\:flag-hu:" => "🇭🇺",
    "\\:flag-ic:" => "🇮🇨",
    "\\:flag-id:" => "🇮🇩",
    "\\:flag-ie:" => "🇮🇪",
    "\\:flag-il:" => "🇮🇱",
    "\\:flag-im:" => "🇮🇲",
    "\\:flag-in:" => "🇮🇳",
    "\\:flag-io:" => "🇮🇴",
    "\\:flag-iq:" => "🇮🇶",
    "\\:flag-ir:" => "🇮🇷",
    "\\:flag-is:" => "🇮🇸",
    "\\:flag-je:" => "🇯🇪",
    "\\:flag-jm:" => "🇯🇲",
    "\\:flag-jo:" => "🇯🇴",
    "\\:flag-ke:" => "🇰🇪",
    "\\:flag-kg:" => "🇰🇬",
    "\\:flag-kh:" => "🇰🇭",
    "\\:flag-ki:" => "🇰🇮",
    "\\:flag-km:" => "🇰🇲",
    "\\:flag-kn:" => "🇰🇳",
    "\\:flag-kp:" => "🇰🇵",
    "\\:flag-kw:" => "🇰🇼",
    "\\:flag-ky:" => "🇰🇾",
    "\\:flag-kz:" => "🇰🇿",
    "\\:flag-la:" => "🇱🇦",
    "\\:flag-lb:" => "🇱🇧",
    "\\:flag-lc:" => "🇱🇨",
    "\\:flag-li:" => "🇱🇮",
    "\\:flag-lk:" => "🇱🇰",
    "\\:flag-lr:" => "🇱🇷",
    "\\:flag-ls:" => "🇱🇸",
    "\\:flag-lt:" => "🇱🇹",
    "\\:flag-lu:" => "🇱🇺",
    "\\:flag-lv:" => "🇱🇻",
    "\\:flag-ly:" => "🇱🇾",
    "\\:flag-ma:" => "🇲🇦",
    "\\:flag-mc:" => "🇲🇨",
    "\\:flag-md:" => "🇲🇩",
    "\\:flag-me:" => "🇲🇪",
    "\\:flag-mf:" => "🇲🇫",
    "\\:flag-mg:" => "🇲🇬",
    "\\:flag-mh:" => "🇲🇭",
    "\\:flag-mk:" => "🇲🇰",
    "\\:flag-ml:" => "🇲🇱",
    "\\:flag-mm:" => "🇲🇲",
    "\\:flag-mn:" => "🇲🇳",
    "\\:flag-mo:" => "🇲🇴",
    "\\:flag-mp:" => "🇲🇵",
    "\\:flag-mq:" => "🇲🇶",
    "\\:flag-mr:" => "🇲🇷",
    "\\:flag-ms:" => "🇲🇸",
    "\\:flag-mt:" => "🇲🇹",
    "\\:flag-mu:" => "🇲🇺",
    "\\:flag-mv:" => "🇲🇻",
    "\\:flag-mw:" => "🇲🇼",
    "\\:flag-mx:" => "🇲🇽",
    "\\:flag-my:" => "🇲🇾",
    "\\:flag-mz:" => "🇲🇿",
    "\\:flag-na:" => "🇳🇦",
    "\\:flag-nc:" => "🇳🇨",
    "\\:flag-ne:" => "🇳🇪",
    "\\:flag-nf:" => "🇳🇫",
    "\\:flag-ng:" => "🇳🇬",
    "\\:flag-ni:" => "🇳🇮",
    "\\:flag-nl:" => "🇳🇱",
    "\\:flag-no:" => "🇳🇴",
    "\\:flag-np:" => "🇳🇵",
    "\\:flag-nr:" => "🇳🇷",
    "\\:flag-nu:" => "🇳🇺",
    "\\:flag-nz:" => "🇳🇿",
    "\\:flag-om:" => "🇴🇲",
    "\\:flag-pa:" => "🇵🇦",
    "\\:flag-pe:" => "🇵🇪",
    "\\:flag-pf:" => "🇵🇫",
    "\\:flag-pg:" => "🇵🇬",
    "\\:flag-ph:" => "🇵🇭",
    "\\:flag-pk:" => "🇵🇰",
    "\\:flag-pl:" => "🇵🇱",
    "\\:flag-pm:" => "🇵🇲",
    "\\:flag-pn:" => "🇵🇳",
    "\\:flag-pr:" => "🇵🇷",
    "\\:flag-ps:" => "🇵🇸",
    "\\:flag-pt:" => "🇵🇹",
    "\\:flag-pw:" => "🇵🇼",
    "\\:flag-py:" => "🇵🇾",
    "\\:flag-qa:" => "🇶🇦",
    "\\:flag-re:" => "🇷🇪",
    "\\:flag-ro:" => "🇷🇴",
    "\\:flag-rs:" => "🇷🇸",
    "\\:flag-rw:" => "🇷🇼",
    "\\:flag-sa:" => "🇸🇦",
    "\\:flag-sb:" => "🇸🇧",
    "\\:flag-sc:" => "🇸🇨",
    "\\:flag-scotland:" => "🏴\Ue0067\Ue0062\Ue0073\Ue0063\Ue0074\Ue007f",
    "\\:flag-sd:" => "🇸🇩",
    "\\:flag-se:" => "🇸🇪",
    "\\:flag-sg:" => "🇸🇬",
    "\\:flag-sh:" => "🇸🇭",
    "\\:flag-si:" => "🇸🇮",
    "\\:flag-sj:" => "🇸🇯",
    "\\:flag-sk:" => "🇸🇰",
    "\\:flag-sl:" => "🇸🇱",
    "\\:flag-sm:" => "🇸🇲",
    "\\:flag-sn:" => "🇸🇳",
    "\\:flag-so:" => "🇸🇴",
    "\\:flag-sr:" => "🇸🇷",
    "\\:flag-ss:" => "🇸🇸",
    "\\:flag-st:" => "🇸🇹",
    "\\:flag-sv:" => "🇸🇻",
    "\\:flag-sx:" => "🇸🇽",
    "\\:flag-sy:" => "🇸🇾",
    "\\:flag-sz:" => "🇸🇿",
    "\\:flag-ta:" => "🇹🇦",
    "\\:flag-tc:" => "🇹🇨",
    "\\:flag-td:" => "🇹🇩",
    "\\:flag-tf:" => "🇹🇫",
    "\\:flag-tg:" => "🇹🇬",
    "\\:flag-th:" => "🇹🇭",
    "\\:flag-tj:" => "🇹🇯",
    "\\:flag-tk:" => "🇹🇰",
    "\\:flag-tl:" => "🇹🇱",
    "\\:flag-tm:" => "🇹🇲",
    "\\:flag-tn:" => "🇹🇳",
    "\\:flag-to:" => "🇹🇴",
    "\\:flag-tr:" => "🇹🇷",
    "\\:flag-tt:" => "🇹🇹",
    "\\:flag-tv:" => "🇹🇻",
    "\\:flag-tw:" => "🇹🇼",
    "\\:flag-tz:" => "🇹🇿",
    "\\:flag-ua:" => "🇺🇦",
    "\\:flag-ug:" => "🇺🇬",
    "\\:flag-um:" => "🇺🇲",
    "\\:flag-un:" => "🇺🇳",
    "\\:flag-uy:" => "🇺🇾",
    "\\:flag-uz:" => "🇺🇿",
    "\\:flag-va:" => "🇻🇦",
    "\\:flag-vc:" => "🇻🇨",
    "\\:flag-ve:" => "🇻🇪",
    "\\:flag-vg:" => "🇻🇬",
    "\\:flag-vi:" => "🇻🇮",
    "\\:flag-vn:" => "🇻🇳",
    "\\:flag-vu:" => "🇻🇺",
    "\\:flag-wales:" => "🏴\Ue0067\Ue0062\Ue0077\Ue006c\Ue0073\Ue007f",
    "\\:flag-wf:" => "🇼🇫",
    "\\:flag-ws:" => "🇼🇸",
    "\\:flag-xk:" => "🇽🇰",
    "\\:flag-ye:" => "🇾🇪",
    "\\:flag-yt:" => "🇾🇹",
    "\\:flag-za:" => "🇿🇦",
    "\\:flag-zm:" => "🇿🇲",
    "\\:flag-zw:" => "🇿🇼",
    "\\:fleur_de_lis:" => "⚜",
    "\\:fog:" => "🌫",
    "\\:four:" => "4⃣",
    "\\:fr:" => "🇫🇷",
    "\\:frame_with_picture:" => "🖼",
    "\\:funeral_urn:" => "⚱",
    "\\:gb:" => "🇬🇧",
    "\\:gear:" => "⚙",
    "\\:golfer:" => "🏌",
    "\\:hammer_and_pick:" => "⚒",
    "\\:hammer_and_wrench:" => "🛠",
    "\\:hash:" => "#⃣",
    "\\:health_worker:" => "🧑\u200d⚕",
    "\\:heart:" => "❤",
    "\\:heart_on_fire:" => "❤\u200d🔥",
    "\\:hearts:" => "♥",
    "\\:heavy_check_mark:" => "✔",
    "\\:heavy_heart_exclamation_mark_ornament:" => "❣",
    "\\:heavy_multiplication_x:" => "✖",
    "\\:helmet_with_white_cross:" => "⛑",
    "\\:hole:" => "🕳",
    "\\:hot_pepper:" => "🌶",
    "\\:hotsprings:" => "♨",
    "\\:house_buildings:" => "🏘",
    "\\:ice_skate:" => "⛸",
    "\\:infinity:" => "♾",
    "\\:information_source:" => "ℹ",
    "\\:interrobang:" => "⁉",
    "\\:it:" => "🇮🇹",
    "\\:joystick:" => "🕹",
    "\\:jp:" => "🇯🇵",
    "\\:judge:" => "🧑\u200d⚖",
    "\\:keyboard:" => "⌨",
    "\\:keycap_star:" => "*⃣",
    "\\:knife_fork_plate:" => "🍽",
    "\\:kr:" => "🇰🇷",
    "\\:label:" => "🏷",
    "\\:latin_cross:" => "✝",
    "\\:left_right_arrow:" => "↔",
    "\\:left_speech_bubble:" => "🗨",
    "\\:leftwards_arrow_with_hook:" => "↩",
    "\\:level_slider:" => "🎚",
    "\\:lightning:" => "🌩",
    "\\:linked_paperclips:" => "🖇",
    "\\:lower_left_ballpoint_pen:" => "🖊",
    "\\:lower_left_crayon:" => "🖍",
    "\\:lower_left_fountain_pen:" => "🖋",
    "\\:lower_left_paintbrush:" => "🖌",
    "\\:m:" => "Ⓜ",
    "\\:male-artist:" => "👨\u200d🎨",
    "\\:male-astronaut:" => "👨\u200d🚀",
    "\\:male-construction-worker:" => "👷\u200d♂",
    "\\:male-cook:" => "👨\u200d🍳",
    "\\:male-detective:" => "🕵\u200d♂",
    "\\:male-doctor:" => "👨\u200d⚕",
    "\\:male-factory-worker:" => "👨\u200d🏭",
    "\\:male-farmer:" => "👨\u200d🌾",
    "\\:male-firefighter:" => "👨\u200d🚒",
    "\\:male-guard:" => "💂\u200d♂",
    "\\:male-judge:" => "👨\u200d⚖",
    "\\:male-mechanic:" => "👨\u200d🔧",
    "\\:male-office-worker:" => "👨\u200d💼",
    "\\:male-pilot:" => "👨\u200d✈",
    "\\:male-police-officer:" => "👮\u200d♂",
    "\\:male-scientist:" => "👨\u200d🔬",
    "\\:male-singer:" => "👨\u200d🎤",
    "\\:male-student:" => "👨\u200d🎓",
    "\\:male-teacher:" => "👨\u200d🏫",
    "\\:male-technologist:" => "👨\u200d💻",
    "\\:male_elf:" => "🧝\u200d♂",
    "\\:male_fairy:" => "🧚\u200d♂",
    "\\:male_genie:" => "🧞\u200d♂",
    "\\:male_mage:" => "🧙\u200d♂",
    "\\:male_sign:" => "♂",
    "\\:male_superhero:" => "🦸\u200d♂",
    "\\:male_supervillain:" => "🦹\u200d♂",
    "\\:male_vampire:" => "🧛\u200d♂",
    "\\:male_zombie:" => "🧟\u200d♂",
    "\\:man-biking:" => "🚴\u200d♂",
    "\\:man-bouncing-ball:" => "⛹\u200d♂",
    "\\:man-bowing:" => "🙇\u200d♂",
    "\\:man-boy-boy:" => "👨\u200d👦\u200d👦",
    "\\:man-boy:" => "👨\u200d👦",
    "\\:man-cartwheeling:" => "🤸\u200d♂",
    "\\:man-facepalming:" => "🤦\u200d♂",
    "\\:man-frowning:" => "🙍\u200d♂",
    "\\:man-gesturing-no:" => "🙅\u200d♂",
    "\\:man-gesturing-ok:" => "🙆\u200d♂",
    "\\:man-getting-haircut:" => "💇\u200d♂",
    "\\:man-getting-massage:" => "💆\u200d♂",
    "\\:man-girl-boy:" => "👨\u200d👧\u200d👦",
    "\\:man-girl-girl:" => "👨\u200d👧\u200d👧",
    "\\:man-girl:" => "👨\u200d👧",
    "\\:man-golfing:" => "🏌\u200d♂",
    "\\:man-heart-man:" => "👨\u200d❤\u200d👨",
    "\\:man-juggling:" => "🤹\u200d♂",
    "\\:man-kiss-man:" => "👨\u200d❤\u200d💋\u200d👨",
    "\\:man-lifting-weights:" => "🏋\u200d♂",
    "\\:man-man-boy-boy:" => "👨\u200d👨\u200d👦\u200d👦",
    "\\:man-man-boy:" => "👨\u200d👨\u200d👦",
    "\\:man-man-girl-boy:" => "👨\u200d👨\u200d👧\u200d👦",
    "\\:man-man-girl-girl:" => "👨\u200d👨\u200d👧\u200d👧",
    "\\:man-man-girl:" => "👨\u200d👨\u200d👧",
    "\\:man-mountain-biking:" => "🚵\u200d♂",
    "\\:man-playing-handball:" => "🤾\u200d♂",
    "\\:man-playing-water-polo:" => "🤽\u200d♂",
    "\\:man-pouting:" => "🙎\u200d♂",
    "\\:man-raising-hand:" => "🙋\u200d♂",
    "\\:man-rowing-boat:" => "🚣\u200d♂",
    "\\:man-running:" => "🏃\u200d♂",
    "\\:man-shrugging:" => "🤷\u200d♂",
    "\\:man-surfing:" => "🏄\u200d♂",
    "\\:man-swimming:" => "🏊\u200d♂",
    "\\:man-tipping-hand:" => "💁\u200d♂",
    "\\:man-walking:" => "🚶\u200d♂",
    "\\:man-wearing-turban:" => "👳\u200d♂",
    "\\:man-woman-boy-boy:" => "👨\u200d👩\u200d👦\u200d👦",
    "\\:man-woman-boy:" => "👨\u200d👩\u200d👦",
    "\\:man-woman-girl-boy:" => "👨\u200d👩\u200d👧\u200d👦",
    "\\:man-woman-girl-girl:" => "👨\u200d👩\u200d👧\u200d👧",
    "\\:man-woman-girl:" => "👨\u200d👩\u200d👧",
    "\\:man-wrestling:" => "🤼\u200d♂",
    "\\:man_climbing:" => "🧗\u200d♂",
    "\\:man_feeding_baby:" => "👨\u200d🍼",
    "\\:man_in_business_suit_levitating:" => "🕴",
    "\\:man_in_lotus_position:" => "🧘\u200d♂",
    "\\:man_in_manual_wheelchair:" => "👨\u200d🦽",
    "\\:man_in_motorized_wheelchair:" => "👨\u200d🦼",
    "\\:man_in_steamy_room:" => "🧖\u200d♂",
    "\\:man_in_tuxedo:" => "🤵\u200d♂",
    "\\:man_kneeling:" => "🧎\u200d♂",
    "\\:man_standing:" => "🧍\u200d♂",
    "\\:man_with_beard:" => "🧔\u200d♂",
    "\\:man_with_probing_cane:" => "👨\u200d🦯",
    "\\:man_with_veil:" => "👰\u200d♂",
    "\\:mantelpiece_clock:" => "🕰",
    "\\:mechanic:" => "🧑\u200d🔧",
    "\\:medal:" => "🎖",
    "\\:medical_symbol:" => "⚕",
    "\\:men-with-bunny-ears-partying:" => "👯\u200d♂",
    "\\:mending_heart:" => "❤\u200d🩹",
    "\\:mermaid:" => "🧜\u200d♀",
    "\\:merman:" => "🧜\u200d♂",
    "\\:mostly_sunny:" => "🌤",
    "\\:motor_boat:" => "🛥",
    "\\:motorway:" => "🛣",
    "\\:mountain:" => "⛰",
    "\\:mx_claus:" => "🧑\u200d🎄",
    "\\:national_park:" => "🏞",
    "\\:nine:" => "9⃣",
    "\\:o2:" => "🅾",
    "\\:office_worker:" => "🧑\u200d💼",
    "\\:oil_drum:" => "🛢",
    "\\:old_key:" => "🗝",
    "\\:om_symbol:" => "🕉",
    "\\:one:" => "1⃣",
    "\\:orthodox_cross:" => "☦",
    "\\:parking:" => "🅿",
    "\\:part_alternation_mark:" => "〽",
    "\\:partly_sunny_rain:" => "🌦",
    "\\:passenger_ship:" => "🛳",
    "\\:peace_symbol:" => "☮",
    "\\:pencil2:" => "✏",
    "\\:people_holding_hands:" => "🧑\u200d🤝\u200d🧑",
    "\\:person_feeding_baby:" => "🧑\u200d🍼",
    "\\:person_in_manual_wheelchair:" => "🧑\u200d🦽",
    "\\:person_in_motorized_wheelchair:" => "🧑\u200d🦼",
    "\\:person_with_ball:" => "⛹",
    "\\:person_with_probing_cane:" => "🧑\u200d🦯",
    "\\:phone:" => "☎",
    "\\:pick:" => "⛏",
    "\\:pilot:" => "🧑\u200d✈",
    "\\:pirate_flag:" => "🏴\u200d☠",
    "\\:point_up:" => "☝",
    "\\:polar_bear:" => "🐻\u200d❄",
    "\\:printer:" => "🖨",
    "\\:racing_car:" => "🏎",
    "\\:racing_motorcycle:" => "🏍",
    "\\:radioactive_sign:" => "☢",
    "\\:railway_track:" => "🛤",
    "\\:rain_cloud:" => "🌧",
    "\\:rainbow-flag:" => "🏳\u200d🌈",
    "\\:raised_hand_with_fingers_splayed:" => "🖐",
    "\\:recycle:" => "♻",
    "\\:red_haired_man:" => "👨\u200d🦰",
    "\\:red_haired_person:" => "🧑\u200d🦰",
    "\\:red_haired_woman:" => "👩\u200d🦰",
    "\\:registered:" => "®",
    "\\:relaxed:" => "☺",
    "\\:reminder_ribbon:" => "🎗",
    "\\:right_anger_bubble:" => "🗯",
    "\\:rolled_up_newspaper:" => "🗞",
    "\\:rosette:" => "🏵",
    "\\:ru:" => "🇷🇺",
    "\\:sa:" => "🈂",
    "\\:satellite:" => "🛰",
    "\\:scales:" => "⚖",
    "\\:scientist:" => "🧑\u200d🔬",
    "\\:scissors:" => "✂",
    "\\:secret:" => "㊙",
    "\\:service_dog:" => "🐕\u200d🦺",
    "\\:seven:" => "7⃣",
    "\\:shamrock:" => "☘",
    "\\:shield:" => "🛡",
    "\\:shinto_shrine:" => "⛩",
    "\\:shopping_bags:" => "🛍",
    "\\:singer:" => "🧑\u200d🎤",
    "\\:six:" => "6⃣",
    "\\:skier:" => "⛷",
    "\\:skull_and_crossbones:" => "☠",
    "\\:sleuth_or_spy:" => "🕵",
    "\\:small_airplane:" => "🛩",
    "\\:snow_capped_mountain:" => "🏔",
    "\\:snow_cloud:" => "🌨",
    "\\:snowflake:" => "❄",
    "\\:snowman:" => "☃",
    "\\:spades:" => "♠",
    "\\:sparkle:" => "❇",
    "\\:speaking_head_in_silhouette:" => "🗣",
    "\\:spider:" => "🕷",
    "\\:spider_web:" => "🕸",
    "\\:spiral_calendar_pad:" => "🗓",
    "\\:spiral_note_pad:" => "🗒",
    "\\:stadium:" => "🏟",
    "\\:star_and_crescent:" => "☪",
    "\\:star_of_david:" => "✡",
    "\\:stopwatch:" => "⏱",
    "\\:student:" => "🧑\u200d🎓",
    "\\:studio_microphone:" => "🎙",
    "\\:sunny:" => "☀",
    "\\:teacher:" => "🧑\u200d🏫",
    "\\:technologist:" => "🧑\u200d💻",
    "\\:thermometer:" => "🌡",
    "\\:three:" => "3⃣",
    "\\:three_button_mouse:" => "🖱",
    "\\:thunder_cloud_and_rain:" => "⛈",
    "\\:timer_clock:" => "⏲",
    "\\:tm:" => "™",
    "\\:tornado:" => "🌪",
    "\\:trackball:" => "🖲",
    "\\:transgender_flag:" => "🏳\u200d⚧",
    "\\:transgender_symbol:" => "⚧",
    "\\:two:" => "2⃣",
    "\\:u6708:" => "🈷",
    "\\:umbrella:" => "☂",
    "\\:umbrella_on_ground:" => "⛱",
    "\\:us:" => "🇺🇸",
    "\\:v:" => "✌",
    "\\:warning:" => "⚠",
    "\\:wastebasket:" => "🗑",
    "\\:waving_white_flag:" => "🏳",
    "\\:wavy_dash:" => "〰",
    "\\:weight_lifter:" => "🏋",
    "\\:wheel_of_dharma:" => "☸",
    "\\:white_frowning_face:" => "☹",
    "\\:white_haired_man:" => "👨\u200d🦳",
    "\\:white_haired_person:" => "🧑\u200d🦳",
    "\\:white_haired_woman:" => "👩\u200d🦳",
    "\\:white_medium_square:" => "◻",
    "\\:white_small_square:" => "▫",
    "\\:wind_blowing_face:" => "🌬",
    "\\:woman-biking:" => "🚴\u200d♀",
    "\\:woman-bouncing-ball:" => "⛹\u200d♀",
    "\\:woman-bowing:" => "🙇\u200d♀",
    "\\:woman-boy-boy:" => "👩\u200d👦\u200d👦",
    "\\:woman-boy:" => "👩\u200d👦",
    "\\:woman-cartwheeling:" => "🤸\u200d♀",
    "\\:woman-facepalming:" => "🤦\u200d♀",
    "\\:woman-frowning:" => "🙍\u200d♀",
    "\\:woman-gesturing-no:" => "🙅\u200d♀",
    "\\:woman-gesturing-ok:" => "🙆\u200d♀",
    "\\:woman-getting-haircut:" => "💇\u200d♀",
    "\\:woman-getting-massage:" => "💆\u200d♀",
    "\\:woman-girl-boy:" => "👩\u200d👧\u200d👦",
    "\\:woman-girl-girl:" => "👩\u200d👧\u200d👧",
    "\\:woman-girl:" => "👩\u200d👧",
    "\\:woman-golfing:" => "🏌\u200d♀",
    "\\:woman-heart-man:" => "👩\u200d❤\u200d👨",
    "\\:woman-heart-woman:" => "👩\u200d❤\u200d👩",
    "\\:woman-juggling:" => "🤹\u200d♀",
    "\\:woman-kiss-man:" => "👩\u200d❤\u200d💋\u200d👨",
    "\\:woman-kiss-woman:" => "👩\u200d❤\u200d💋\u200d👩",
    "\\:woman-lifting-weights:" => "🏋\u200d♀",
    "\\:woman-mountain-biking:" => "🚵\u200d♀",
    "\\:woman-playing-handball:" => "🤾\u200d♀",
    "\\:woman-playing-water-polo:" => "🤽\u200d♀",
    "\\:woman-pouting:" => "🙎\u200d♀",
    "\\:woman-raising-hand:" => "🙋\u200d♀",
    "\\:woman-rowing-boat:" => "🚣\u200d♀",
    "\\:woman-running:" => "🏃\u200d♀",
    "\\:woman-shrugging:" => "🤷\u200d♀",
    "\\:woman-surfing:" => "🏄\u200d♀",
    "\\:woman-swimming:" => "🏊\u200d♀",
    "\\:woman-tipping-hand:" => "💁\u200d♀",
    "\\:woman-walking:" => "🚶\u200d♀",
    "\\:woman-wearing-turban:" => "👳\u200d♀",
    "\\:woman-woman-boy-boy:" => "👩\u200d👩\u200d👦\u200d👦",
    "\\:woman-woman-boy:" => "👩\u200d👩\u200d👦",
    "\\:woman-woman-girl-boy:" => "👩\u200d👩\u200d👧\u200d👦",
    "\\:woman-woman-girl-girl:" => "👩\u200d👩\u200d👧\u200d👧",
    "\\:woman-woman-girl:" => "👩\u200d👩\u200d👧",
    "\\:woman-wrestling:" => "🤼\u200d♀",
    "\\:woman_climbing:" => "🧗\u200d♀",
    "\\:woman_feeding_baby:" => "👩\u200d🍼",
    "\\:woman_in_lotus_position:" => "🧘\u200d♀",
    "\\:woman_in_manual_wheelchair:" => "👩\u200d🦽",
    "\\:woman_in_motorized_wheelchair:" => "👩\u200d🦼",
    "\\:woman_in_steamy_room:" => "🧖\u200d♀",
    "\\:woman_in_tuxedo:" => "🤵\u200d♀",
    "\\:woman_kneeling:" => "🧎\u200d♀",
    "\\:woman_standing:" => "🧍\u200d♀",
    "\\:woman_with_beard:" => "🧔\u200d♀",
    "\\:woman_with_probing_cane:" => "👩\u200d🦯",
    "\\:woman_with_veil:" => "👰\u200d♀",
    "\\:women-with-bunny-ears-partying:" => "👯\u200d♀",
    "\\:world_map:" => "🗺",
    "\\:writing_hand:" => "✍",
    "\\:yin_yang:" => "☯",
    "\\:zero:" => "0⃣",
)


text:
function print_field_types(io::IO, struct_instance)
    fields = fieldnames(typeof(struct_instance))
    types = [typeof(getproperty(struct_instance, field)) for field in fields]
    field_types = string.(fields).*": ".*string.(types)
    field_types = "   ".*string.(field_types).*("\n")
    print(io, field_types...)
end

function print_field_names(io::IO, struct_instance)
    fields = fieldnames(typeof(struct_instance))
    types = [nameof(typeof(getproperty(struct_instance, field))) for field in fields]
    field_types = string.(fields).*": ".*string.(types)
    field_types = "   ".*string.(field_types).*("\n")
    print(io, field_types...)
end

function print_type_name(io::IO, struct_instance)
    print(io, nameof(typeof(struct_instance))); print(io, "\n")
end

function print_type(io::IO, struct_instance)
    print(io, typeof(struct_instance)); print(io, "\n")
end

##############################################################
# Loss Functions, Imply,
##############################################################

function Base.show(io::IO, struct_inst::SemLossFunction)
    print_type_name(io, struct_inst)
    print_field_types(io, struct_inst)
end

function Base.show(io::IO, struct_inst::SemImply)
    print_type_name(io, struct_inst)
    print_field_types(io, struct_inst)
end

function Base.show(io::IO, struct_inst::SemObserved)
    print_type_name(io, struct_inst)
    print_field_types(io, struct_inst)
end

function Base.show(io::IO, struct_inst::SemOptimizer)
    print_type_name(io, struct_inst)
    print_field_types(io, struct_inst)
end


text:
using BayesianSumProductNetworks
using Test, Random
using AxisArrays, StatsFuns

priors = [NormalInverseGamma(0.0, 1.0, 1.0, 1.0), Beta()]
likelihoods = [Normal(), Bernoulli()]
sstats = [NormalInvGammaSufficientStats(), BetaSufficientStats()]
prior_sums_alpha = 1.0
prior_prods_alpha = 10.0
prior_leaves_alpha = 0.01
J = 2
K = 10
K_sum = 4
K_prod = 2

N = 100
D = 2

Random.seed!(1)
x = hcat(randn(N,1), rand(0:1, N,1))

# SPN
spn = templateRegion(prior_sums_alpha, prior_prods_alpha, prior_leaves_alpha,
    priors, likelihoods, sstats, N, D, K_sum, K_prod, J, K, 1, 2, root = true)

# Initialization
randomscopes!(spn, x)

@test scope(spn) == [1,2]

# Single ancestral sampling step
ancestralsampling!(spn, x)

@test sum(exp.(spn.logweights)) ≈ 1

# SPN
spn = templateRegion(prior_sums_alpha,
    prior_prods_alpha, prior_leaves_alpha, priors, likelihoods,
    sstats, N, D, K_sum, K_prod, J, K, 1, 2, root = true)

# Initialization
Random.seed!(1)
randomscopes!(spn, x)

performance = Vector()
llhvals = ones(N) * -Inf
for i in 1:1000
    ancestralsampling!(spn, x)
    llhvals_ = logpdf(spn, x)
    for n in 1:N
        @inbounds begin
            llhvals[n] = logaddexp(llhvals[n], llhvals_[n])
        end
    end
    push!(performance, mean(llhvals) - log(i))
end

@test last(performance) ≈ -2.1 atol=0.1

# SPN
spn = templateRegion(prior_sums_alpha,
    prior_prods_alpha, prior_leaves_alpha, priors, likelihoods,
    sstats, N, D, 5, 2, 2, 5, 1, 4, root = true)

# Initialization
randomscopes!(spn, x)

ancestralsampling!(spn, x);

# Test region graph for heterogenuous data
priors = [[Beta(1, 1), Gamma()], [NormalInverseGamma(1.0, 1.0, 1.0, 1.0), Gamma()]]
likelihoods = [Distribution[Bernoulli(), Poisson()], Distribution[Normal(), Exponential()]]
sstats = [[BetaSufficientStats(), GammaSufficienStats()], [NormalInvGammaSufficientStats(), GammaSufficienStats()]]

Random.seed!(1)
x = hcat(rand(0:1,N,1), randn(N,1))
x[:,2] .-= minimum(x[:,2])

# SPN
spn = templateRegion(prior_sums_alpha, prior_prods_alpha, prior_leaves_alpha,
    priors, likelihoods, sstats, N, D, K_sum, K_prod, J, K, 1, 2, root = true)

# Initialization
Random.seed!(1)
randomscopes!(spn, x)

performance = Vector()
llhvals = ones(N) * -Inf
for i in 1:1000
    ancestralsampling!(spn, x)
    llhvals_ = logpdf(spn, x)
    for n in 1:N
        @inbounds begin
            llhvals[n] = logaddexp(llhvals[n], llhvals_[n])
        end
    end
    push!(performance, mean(llhvals) - log(i))
end

@test last(performance) ≈ -2.2 atol=0.1

max_stars_repo_name: crinders/BayesianSumProductNetworks

max_issues_repo_name: crinders/BayesianSumProductNetworks

max_forks_repo_name: crinders/BayesianSumProductNetworks


text:
using SimpleGraphs, ProgressMeter, SemiIsomorphism

struct Trees
    n::Int
end

function Base.iterate(T::Trees, state = 0)
    N = T.n
    NN = Int128(N)^(N - 2)
    if state == NN
        return nothing
    end

    code = Int.(digits(state, base = N, pad = N - 2) .+ 1)
    G = prufer_restore(code)
    name(G, "Tree")
    return (G, state + 1)
end

Base.length(T::Trees) = Int128(T.n)^(T.n - 2)

"""
    distinct_trees(n)
Returns a list of all trees on `n` vertices that are pairwise non-isomorphic.

**WARNINGS**
+ This can be used up to `n = 9`. Beyond that it's very slows.
+ Filtering out isomorphic duplicates is done by a heuristic. Tested up to `n = 9` and it works.

See https://oeis.org/A000055
"""
function distinct_trees(n::Int)
    result = Set{SimpleGraph{Int}}()
    seen = Set{UInt64}()
    P = Progress(length(Trees(n)))
    for T ∈ Trees(n)
        next!(P)
        uh = uhash(T)
        if uh ∈ seen
            continue
        end
        push!(seen, uh)
        push!(result, T)
    end
    return collect(result)
end

function find_semi_iso_pair(list::Vector{SimpleGraph{T}}) where {T}
    nG = length(list)
    for j = 1:nG-1
        for k = j+1:nG
            if is_semi_iso(TT[j], TT[k])
                return TT[j], TT[k]
            end
        end
    end
    println("No pair found")
    nothing
end

function find_frac_iso_pair(list::Vector{SimpleGraph{T}}) where {T}
    nG = length(list)
    for j = 1:nG-1
        for k = j+1:nG
            if is_fiso(TT[j], TT[k])
                return TT[j], TT[k]
            end
        end
    end
    println("No pair found")
    nothing
end


text:
struct Linear; w; b; end

function Linear(inputsize::Int, outputsize::Int)
    Linear(param(outputsize,inputsize), param0(outputsize))
end

function (l::Linear)(x)
    l.w * x .+ l.b
end

max_stars_repo_name: denizyuret/research

max_issues_repo_name: denizyuret/research

max_forks_repo_name: denizyuret/research


text:
module MakieGallery

using AbstractPlotting
using Documenter
using Documenter: Selectors, Expanders
using Markdown
using Markdown: Link, Paragraph
using ImageTransformations, FileIO
using ImageFiltering  # needed for Gaussian-filtering images during resize
using Random
using Documenter.Writers
using Documenter.Writers.HTMLWriter
using Test, Statistics
using BinaryProvider

include("documenter_extension.jl")
include("database.jl")
include("io.jl")
include("gallery.jl")
include("visualregression.jl")
include("testruns.jl")

function event_path(entry, ending)
    joinpath(@__DIR__, "..", "examples", "recorded_events", string(entry.unique_name, ".jls"))
end

"""
Loads the example database and returns it!
"""
function load_database()
    empty!(unique_names)
    empty!(database)
    dir = abspath(joinpath(dirname(pathof(MakieGallery)), ".."))
    files = [
        "$dir/examples/tutorials.jl",
        "$dir/examples/examples2d.jl",
        "$dir/examples/examples3d.jl",
        "$dir/examples/interactive.jl",
        "$dir/examples/documentation.jl",
        "$dir/examples/implicits.jl",
        "$dir/examples/short_tests.jl",
        "$dir/examples/recipes.jl",
        "$dir/examples/bigdata.jl",
        "$dir/examples/layouting.jl",
        "$dir/examples/statsmakie.jl",
    ]
    for file in files
        MakieGallery.eval(:(include($file)))
    end
    database
end

end


text:
# ============================================================
# Fluxes for Control Volume Structures
# ============================================================

"""
Evolve field solution

* particle evolution: KFVS, KCU, UGKS
* electromagnetic evolution: wave propagation method

"""
function evolve!(
    KS::SolverSet,
    uq::AbstractUQ,
    ctr::AbstractArray{<:AbstractControlVolume1D,1},
    face::AbstractArray{<:AbstractInterface1D,1},
    dt::AbstractFloat;
    mode = :kfvs::Symbol,
    isPlasma = true::Bool,
    isMHD = false:Bool,
)

    # flow field
    if uq.method == "collocation"
        @inbounds Threads.@threads for i in eachindex(face)
            uqflux_flow_collocation!(
                KS,
                ctr[i-1],
                face[i],
                ctr[i],
                dt,
                mode = mode,
                isMHD = isMHD,
            )
        end
    elseif uq.method == "galerkin"
        @inbounds Threads.@threads for i in eachindex(face)
            uqflux_flow_galerkin!(
                KS,
                uq,
                ctr[i-1],
                face[i],
                ctr[i],
                dt,
                mode = mode,
                isMHD = isMHD,
            )
        end
    else
        throw("UQ method isn't available")
    end

    # electromagnetic field
    if isPlasma
        @inbounds Threads.@threads for i in eachindex(face)
            uqflux_em!(KS, uq, ctr[i-2], ctr[i-1], face[i], ctr[i], ctr[i+1], dt)
        end
    end

end

"""
Calculate flux of particle transport

* collocation: `uqflux_flow!(KS::SolverSet, cellL::ControlVolume1D1F, face::Interface1D1F, cellR::ControlVolume1D1F,
    dt::AbstractFloat; mode = :kfvs::Symbol)`
* galerkin: `uqflux_flow!(KS::SolverSet, uq::AbstractUQ, cellL::ControlVolume1D1F, face::Interface1D1F, cellR::ControlVolume1D1F,
    dt::AbstractFloat; mode = :kfvs::Symbol)`

"""
function uqflux_flow_galerkin!(
    KS::T1,
    uq::T2,
    cellL::ControlVolume1D1F,
    face::Interface1D1F,
    cellR::ControlVolume1D1F,
    dt;
    mode = :kfvs::Symbol,
    isMHD = false::Bool,
) where {T1<:AbstractSolverSet,T2<:AbstractUQ}

    if mode == :kfvs

        @inbounds for j in axes(cellL.f, 2)
            fw = @view face.fw[:, j]
            ff = @view face.ff[:, j]

            flux_kfvs!(
                fw,
                ff,
                cellL.f[:, j] .+ 0.5 .* cellL.dx .* cellL.sf[:, j],
                cellR.f[:, j] .- 0.5 .* cellR.dx .* cellR.sf[:, j],
                KS.vSpace.u,
                KS.vSpace.weights,
                dt,
                cellL.sf[:, j],
                cellR.sf[:, j],
            )
        end

    elseif mode == :kcu

        fw = chaos_ran(face.fw, 2, uq)
        ff = chaos_ran(face.ff, 2, uq)

        wL = chaos_ran(cellL.w .+ 0.5 .* cellL.dx .* cellL.sw, 2, uq)
        fL = chaos_ran(cellL.f .+ 0.5 .* cellL.dx .* cellL.sf, 2, uq)

        wR = chaos_ran(cellR.w .- 0.5 .* cellR.dx .* cellR.sw, 2, uq)
        fR = chaos_ran(cellR.f .- 0.5 .* cellR.dx .* cellR.sf, 2, uq)

        @inbounds for j in axes(fL, 2)
            _fw = @view fw[:, j]
            _ff = @view ff[:, j]

            flux_kcu!(
                _fw,
                _ff,
                wL[:, j],
                fL[:, j],
                wR[:, j],
                fR[:, j],
                KS.vSpace.u,
                KS.vSpace.weights,
                KS.gas.K,
                KS.gas.γ,
                KS.gas.μᵣ,
                KS.gas.ωᵣ,
                KS.gas.Pr,
                dt,
            )
        end

        face.fw .= chaos_ran(fw, 2, uq)
        face.ff .= chaos_ran(ff, 2, uq)

    elseif mode == :ugks

        fw = chaos_ran(face.fw, 2, uq)
        ff = chaos_ran(face.ff, 2, uq)

        wL = chaos_ran(cellL.w .+ 0.5 .* cellL.dx .* cellL.sw, 2, uq)
        fL = chaos_ran(cellL.f .+ 0.5 .* cellL.dx .* cellL.sf, 2, uq)
        sfL = chaos_ran(cellL.sf, 2, uq)

        wR = chaos_ran(cellR.w .- 0.5 .* cellR.dx .* cellR.sw, 2, uq)
        fR = chaos_ran(cellR.f .- 0.5 .* cellR.dx .* cellR.sf, 2, uq)
        sfR = chaos_ran(cellR.sf, 2, uq)

        @inbounds for j in axes(fL, 2)
            _fw = @view face.fw[:, j]
            _ff = @view face.ff[:, j]

            flux_ugks!(
                _fw,
                _ff,
                wL[:, j],
                fL[:, j],
                wR[:, j],
                fR[:, j],
                KS.vSpace.u,
                KS.vSpace.weights,
                KS.gas.K,
                KS.gas.γ,
                KS.gas.μᵣ,
                KS.gas.ωᵣ,
                KS.gas.Pr,
                dt,
                0.5 * cellL.dx,
                0.5 * cellR.dx,
                sfL[:, j],
                sfR[:, j],
            )
        end

        face.fw .= chaos_ran(fw, 2, uq)
        face.ff .= chaos_ran(ff, 2, uq)

    else

        throw("flux mode not available")

    end # if

end

function uqflux_flow_collocation!(
    KS::SolverSet,
    cellL::ControlVolume1D1F,
    face::Interface1D1F,
    cellR::ControlVolume1D1F,
    dt::AbstractFloat;
    mode = :kfvs::Symbol,
    isMHD = false::Bool,
)

    if mode == :kfvs

        if ndims(cellL.f) == 2 # pure

            @inbounds for j in axes(cellL.f, 2)
                fw = @view face.fw[:, j]
                ff = @view face.ff[:, j]

                flux_kfvs!(
                    fw,
                    ff,
                    cellL.f[:, j] .+ 0.5 .* cellL.dx .* cellL.sf[:, j],
                    cellR.f[:, j] .- 0.5 .* cellR.dx .* cellR.sf[:, j],
                    KS.vSpace.u,
                    KS.vSpace.weights,
                    dt,
                    cellL.sf[:, j],
                    cellR.sf[:, j],
                )
            end

        elseif ndims(cellL.f) == 3 # mixture

            @inbounds for k in axes(cellL.f, 3)
                for j in axes(cellL.f, 2)
                    fw = @view face.fw[:, j, k]
                    ff = @view face.ff[:, j, k]

                    flux_kfvs!(
                        fw,
                        ff,
                        cellL.f[:, j, k] .+ 0.5 .* cellL.dx .* cellL.sf[:, j, k],
                        cellR.f[:, j, k] .- 0.5 .* cellR.dx .* cellR.sf[:, j, k],
                        KS.vSpace.u[:, k],
                        KS.vSpace.weights[:, k],
                        dt,
                        cellL.sf[:, j, k],
                        cellR.sf[:, j, k],
                    )
                end
            end

        else

            throw("inconsistent distribution function size")

        end

    end

end

# ------------------------------------------------------------
# 1D4F1V
# ------------------------------------------------------------
function uqflux_flow_collocation!(
    KS::SolverSet,
    cellL::ControlVolume1D4F,
    face::Interface1D4F,
    cellR::ControlVolume1D4F,
    dt::AbstractFloat;
    mode = :kfvs::Symbol,
    isMHD = false::Bool,
)

    if mode == :kfvs

        @inbounds for j in axes(cellL.h0, 2)
            fw = @view face.fw[:, j, :]
            fh0 = @view face.fh0[:, j, :]
            fh1 = @view face.fh1[:, j, :]
            fh2 = @view face.fh2[:, j, :]
            fh3 = @view face.fh3[:, j, :]

            flux_kfvs!(
                fw,
                fh0,
                fh1,
                fh2,
                fh3,
                cellL.h0[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sh0[:, j, :],
                cellL.h1[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sh1[:, j, :],
                cellL.h2[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sh2[:, j, :],
                cellL.h3[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sh3[:, j, :],
                cellR.h0[:, j, :] .- 0.5 .* cellR.dx .* cellR.sh0[:, j, :],
                cellR.h1[:, j, :] .- 0.5 .* cellR.dx .* cellR.sh1[:, j, :],
                cellR.h2[:, j, :] .- 0.5 .* cellR.dx .* cellR.sh2[:, j, :],
                cellR.h3[:, j, :] .- 0.5 .* cellR.dx .* cellR.sh3[:, j, :],
                KS.vSpace.u,
                KS.vSpace.weights,
                dt,
                cellL.sh0[:, j, :],
                cellL.sh1[:, j, :],
                cellL.sh2[:, j, :],
                cellL.sh3[:, j, :],
                cellR.sh0[:, j, :],
                cellR.sh1[:, j, :],
                cellR.sh2[:, j, :],
                cellR.sh3[:, j, :],
            )
        end

    elseif mode == :kcu

        @inbounds for j in axes(cellL.h0, 2)
            fw = @view face.fw[:, j, :]
            fh0 = @view face.fh0[:, j, :]
            fh1 = @view face.fh1[:, j, :]
            fh2 = @view face.fh2[:, j, :]
            fh3 = @view face.fh3[:, j, :]

            flux_kcu!(
                fw,
                fh0,
                fh1,
                fh2,
                fh3,
                cellL.w[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sw[:, j, :],
                cellL.h0[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sh0[:, j, :],
                cellL.h1[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sh1[:, j, :],
                cellL.h2[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sh2[:, j, :],
                cellL.h3[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sh3[:, j, :],
                cellR.w[:, j, :] .- 0.5 .* cellR.dx .* cellR.sw[:, j, :],
                cellR.h0[:, j, :] .- 0.5 .* cellR.dx .* cellR.sh0[:, j, :],
                cellR.h1[:, j, :] .- 0.5 .* cellR.dx .* cellR.sh1[:, j, :],
                cellR.h2[:, j, :] .- 0.5 .* cellR.dx .* cellR.sh2[:, j, :],
                cellR.h3[:, j, :] .- 0.5 .* cellR.dx .* cellR.sh3[:, j, :],
                KS.vSpace.u,
                KS.vSpace.weights,
                KS.gas.K,
                KS.gas.γ,
                KS.gas.mi,
                KS.gas.ni,
                KS.gas.me,
                KS.gas.ne,
                KS.gas.Kn[1],
                dt,
                isMHD,
            )
        end

    else

        throw("flux mode not available")

    end # if

end

function uqflux_flow_galerkin!(
    KS::SolverSet,
    uq::AbstractUQ,
    cellL::ControlVolume1D3F,
    face::Interface1D3F,
    cellR::ControlVolume1D3F,
    dt::AbstractFloat;
    mode = :kfvs::Symbol,
    isMHD = false::Bool,
)

    if mode == :kfvs

        @inbounds for k in axes(cellL.h0, 4)
            for j in axes(cellL.h0, 3)
                fw = @view face.fw[:, j, k]
                fh0 = @view face.fh0[:, :, j, k]
                fh1 = @view face.fh1[:, :, j, k]
                fh2 = @view face.fh2[:, :, j, k]

                flux_kfvs!(
                    fw,
                    fh0,
                    fh1,
                    fh2,
                    cellL.h0[:, :, j, k] .+ 0.5 .* cellL.dx .* cellL.sh0[:, :, j, k],
                    cellL.h1[:, :, j, k] .+ 0.5 .* cellL.dx .* cellL.sh1[:, :, j, k],
                    cellL.h2[:, :, j, k] .+ 0.5 .* cellL.dx .* cellL.sh2[:, :, j, k],
                    cellR.h0[:, :, j, k] .- 0.5 .* cellR.dx .* cellR.sh0[:, :, j, k],
                    cellR.h1[:, :, j, k] .- 0.5 .* cellR.dx .* cellR.sh1[:, :, j, k],
                    cellR.h2[:, :, j, k] .- 0.5 .* cellR.dx .* cellR.sh2[:, :, j, k],
                    KS.vSpace.u[:, :, k],
                    KS.vSpace.v[:, :, k],
                    KS.vSpace.weights[:, :, k],
                    dt,
                    1.0,
                    cellL.sh0[:, :, j, k],
                    cellL.sh1[:, :, j, k],
                    cellL.sh2[:, :, j, k],
                    cellR.sh0[:, :, j, k],
                    cellR.sh1[:, :, j, k],
                    cellR.sh2[:, :, j, k],
                )
            end
        end

    elseif mode == :kcu

        fw = chaos_ran(face.fw, 2, uq)
        fh0 = chaos_ran(face.fh0, 3, uq)
        fh1 = chaos_ran(face.fh1, 3, uq)
        fh2 = chaos_ran(face.fh2, 3, uq)

        wL = chaos_ran(cellL.w .+ 0.5 .* cellL.dx .* cellL.sw, 2, uq)
        h0L = chaos_ran(cellL.h0 .+ 0.5 .* cellL.dx .* cellL.sh0, 3, uq)
        h1L = chaos_ran(cellL.h1 .+ 0.5 .* cellL.dx .* cellL.sh1, 3, uq)
        h2L = chaos_ran(cellL.h2 .+ 0.5 .* cellL.dx .* cellL.sh2, 3, uq)

        wR = chaos_ran(cellR.w .- 0.5 .* cellR.dx .* cellR.sw, 2, uq)
        h0R = chaos_ran(cellR.h0 .- 0.5 .* cellR.dx .* cellR.sh0, 3, uq)
        h1R = chaos_ran(cellR.h1 .- 0.5 .* cellR.dx .* cellR.sh1, 3, uq)
        h2R = chaos_ran(cellR.h2 .- 0.5 .* cellR.dx .* cellR.sh2, 3, uq)

        @inbounds for j in axes(h0L, 3)
            _fw = @view fw[:, j, :]
            _fh0 = @view fh0[:, :, j, :]
            _fh1 = @view fh1[:, :, j, :]
            _fh2 = @view fh2[:, :, j, :]

            flux_kcu!(
                _fw,
                _fh0,
                _fh1,
                _fh2,
                wL[:, j, :],
                h0L[:, :, j, :],
                h1L[:, :, j, :],
                h2L[:, :, j, :],
                wR[:, j, :],
                h0R[:, :, j, :],
                h1R[:, :, j, :],
                h2R[:, :, j, :],
                KS.vSpace.u,
                KS.vSpace.v,
                KS.vSpace.weights,
                KS.gas.K,
                KS.gas.γ,
                KS.gas.mi,
                KS.gas.ni,
                KS.gas.me,
                KS.gas.ne,
                KS.gas.Kn[1],
                dt,
                1.0,
                isMHD,
            )
        end

        face.fw .= chaos_ran(fw, 2, uq)
        face.fh0 .= chaos_ran(fh0, 3, uq)
        face.fh1 .= chaos_ran(fh1, 3, uq)
        face.fh2 .= chaos_ran(fh2, 3, uq)

    elseif mode == :ugks

        fw = chaos_ran(face.fw, 2, uq)
        fh0 = chaos_ran(face.fh0, 3, uq)
        fh1 = chaos_ran(face.fh1, 3, uq)
        fh2 = chaos_ran(face.fh2, 3, uq)

        wL = chaos_ran(cellL.w .+ 0.5 .* cellL.dx .* cellL.sw, 2, uq)
        h0L = chaos_ran(cellL.h0 .+ 0.5 .* cellL.dx .* cellL.sh0, 3, uq)
        h1L = chaos_ran(cellL.h1 .+ 0.5 .* cellL.dx .* cellL.sh1, 3, uq)
        h2L = chaos_ran(cellL.h2 .+ 0.5 .* cellL.dx .* cellL.sh2, 3, uq)
        sh0L = chaos_ran(cellL.sh0, 3, uq)
        sh1L = chaos_ran(cellL.sh1, 3, uq)
        sh2L = chaos_ran(cellL.sh2, 3, uq)

        wR = chaos_ran(cellR.w .- 0.5 .* cellR.dx .* cellR.sw, 2, uq)
        h0R = chaos_ran(cellR.h0 .- 0.5 .* cellR.dx .* cellR.sh0, 3, uq)
        h1R = chaos_ran(cellR.h1 .- 0.5 .* cellR.dx .* cellR.sh1, 3, uq)
        h2R = chaos_ran(cellR.h2 .- 0.5 .* cellR.dx .* cellR.sh2, 3, uq)
        sh0R = chaos_ran(cellR.sh0, 3, uq)
        sh1R = chaos_ran(cellR.sh1, 3, uq)
        sh2R = chaos_ran(cellR.sh2, 3, uq)

        @inbounds for j in axes(h0L, 3)
            _fw = @view face.fw[:, j, :]
            _fh0 = @view face.fh0[:, :, j, :]
            _fh1 = @view face.fh1[:, :, j, :]
            _fh2 = @view face.fh2[:, :, j, :]

            flux_ugks!(
                _fw,
                _fh0,
                _fh1,
                _fh2,
                wL[:, j, :],
                h0L[:, :, j, :],
                h1L[:, :, j, :],
                h2L[:, :, j, :],
                wR[:, j, :],
                h0R[:, :, j, :],
                h1R[:, :, j, :],
                h2R[:, :, j, :],
                KS.vSpace.u,
                KS.vSpace.v,
                KS.vSpace.weights,
                KS.gas.K,
                KS.gas.γ,
                KS.gas.mi,
                KS.gas.ni,
                KS.gas.me,
                KS.gas.ne,
                KS.gas.Kn[1],
                dt,
                0.5 * cellL.dx,
                0.5 * cellR.dx,
                1.0,
                sh0L[:, :, j, :],
                sh1L[:, :, j, :],
                sh2L[:, :, j, :],
                sh0R[:, :, j, :],
                sh1R[:, :, j, :],
                sh2R[:, :, j, :],
            )
        end

        face.fw .= chaos_ran(fw, 2, uq)
        face.fh0 .= chaos_ran(fh0, 3, uq)
        face.fh1 .= chaos_ran(fh1, 3, uq)
        face.fh2 .= chaos_ran(fh2, 3, uq)

    else

        throw("flux mode not available")

    end # if

end

function uqflux_flow_collocation!(
    KS::SolverSet,
    cellL::ControlVolume1D3F,
    face::Interface1D3F,
    cellR::ControlVolume1D3F,
    dt::AbstractFloat;
    mode = :kfvs::Symbol,
    isMHD = false::Bool,
)

    if mode == :kfvs

        @inbounds for k in axes(cellL.h0, 4)
            for j in axes(cellL.h0, 3)
                fw = @view face.fw[:, j, k]
                fh0 = @view face.fh0[:, :, j, k]
                fh1 = @view face.fh1[:, :, j, k]
                fh2 = @view face.fh2[:, :, j, k]

                flux_kfvs!(
                    fw,
                    fh0,
                    fh1,
                    fh2,
                    cellL.h0[:, :, j, k] .+ 0.5 .* cellL.dx .* cellL.sh0[:, :, j, k],
                    cellL.h1[:, :, j, k] .+ 0.5 .* cellL.dx .* cellL.sh1[:, :, j, k],
                    cellL.h2[:, :, j, k] .+ 0.5 .* cellL.dx .* cellL.sh2[:, :, j, k],
                    cellR.h0[:, :, j, k] .- 0.5 .* cellR.dx .* cellR.sh0[:, :, j, k],
                    cellR.h1[:, :, j, k] .- 0.5 .* cellR.dx .* cellR.sh1[:, :, j, k],
                    cellR.h2[:, :, j, k] .- 0.5 .* cellR.dx .* cellR.sh2[:, :, j, k],
                    KS.vSpace.u[:, :, k],
                    KS.vSpace.v[:, :, k],
                    KS.vSpace.weights[:, :, k],
                    dt,
                    1.0,
                    cellL.sh0[:, :, j, k],
                    cellL.sh1[:, :, j, k],
                    cellL.sh2[:, :, j, k],
                    cellR.sh0[:, :, j, k],
                    cellR.sh1[:, :, j, k],
                    cellR.sh2[:, :, j, k],
                )
            end
        end

    elseif mode == :kcu

        @inbounds for j in axes(cellL.h0, 3)
            fw = @view face.fw[:, j, :]
            fh0 = @view face.fh0[:, :, j, :]
            fh1 = @view face.fh1[:, :, j, :]
            fh2 = @view face.fh2[:, :, j, :]

            flux_kcu!(
                fw,
                fh0,
                fh1,
                fh2,
                cellL.w[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sw[:, j, :],
                cellL.h0[:, :, j, :] .+ 0.5 .* cellL.dx .* cellL.sh0[:, :, j, :],
                cellL.h1[:, :, j, :] .+ 0.5 .* cellL.dx .* cellL.sh1[:, :, j, :],
                cellL.h2[:, :, j, :] .+ 0.5 .* cellL.dx .* cellL.sh2[:, :, j, :],
                cellR.w[:, j, :] .- 0.5 .* cellR.dx .* cellR.sw[:, j, :],
                cellR.h0[:, :, j, :] .- 0.5 .* cellR.dx .* cellR.sh0[:, :, j, :],
                cellR.h1[:, :, j, :] .- 0.5 .* cellR.dx .* cellR.sh1[:, :, j, :],
                cellR.h2[:, :, j, :] .- 0.5 .* cellR.dx .* cellR.sh2[:, :, j, :],
                KS.vSpace.u[:, :, :],
                KS.vSpace.v[:, :, :],
                KS.vSpace.weights[:, :, :],
                KS.gas.K,
                KS.gas.γ,
                KS.gas.mi,
                KS.gas.ni,
                KS.gas.me,
                KS.gas.ne,
                KS.gas.Kn[1],
                dt,
                1.0,
                isMHD,
            )
        end

    elseif mode == :ugks

        @inbounds for j in axes(cellL.h0, 3)
            fw = @view face.fw[:, j, :]
            fh0 = @view face.fh0[:, :, j, :]
            fh1 = @view face.fh1[:, :, j, :]
            fh2 = @view face.fh2[:, :, j, :]

            flux_ugks!(
                fw,
                fh0,
                fh1,
                fh2,
                cellL.w[:, j, :] .+ 0.5 .* cellL.dx .* cellL.sw[:, j, :],
                cellL.h0[:, :, j, :] .+ 0.5 .* cellL.dx .* cellL.sh0[:, :, j, :],
                cellL.h1[:, :, j, :] .+ 0.5 .* cellL.dx .* cellL.sh1[:, :, j, :],
                cellL.h2[:, :, j, :] .+ 0.5 .* cellL.dx .* cellL.sh2[:, :, j, :],
                cellR.w[:, j, :] .- 0.5 .* cellR.dx .* cellR.sw[:, j, :],
                cellR.h0[:, :, j, :] .- 0.5 .* cellR.dx .* cellR.sh0[:, :, j, :],
                cellR.h1[:, :, j, :] .- 0.5 .* cellR.dx .* cellR.sh1[:, :, j, :],
                cellR.h2[:, :, j, :] .- 0.5 .* cellR.dx .* cellR.sh2[:, :, j, :],
                KS.vSpace.u[:, :, :],
                KS.vSpace.v[:, :, :],
                KS.vSpace.weights[:, :, :],
                KS.gas.K,
                KS.gas.γ,
                KS.gas.mi,
                KS.gas.ni,
                KS.gas.me,
                KS.gas.ne,
                KS.gas.Kn[1],
                dt,
                0.5 * cellL.dx,
                0.5 * cellR.dx,
                1.0,
                cellL.sh0[:, :, j, :],
                cellL.sh1[:, :, j, :],
                cellL.sh2[:, :, j, :],
                cellR.sh0[:, :, j, :],
                cellR.sh1[:, :, j, :],
                cellR.sh2[:, :, j, :],
            )
        end

    else

        throw("flux mode not available")

    end # if

end

"""
Calculate flux of electromagnetic propagation

"""
function uqflux_em!(
    KS::SolverSet,
    uq::AbstractUQ,
    cellLL::AbstractControlVolume1D,
    cellL::AbstractControlVolume1D,
    face::AbstractInterface1D,
    cellR::AbstractControlVolume1D,
    cellRR::AbstractControlVolume1D,
    dt::Real,
)

    if uq.method == "collocation"

        for j = 1:uq.op.quad.Nquad
            femL = @view face.femL[:, j]
            femR = @view face.femR[:, j]

            flux_em!(
                femL,
                femR,
                cellLL.E[:, j],
                cellLL.B[:, j],
                cellL.E[:, j],
                cellL.B[:, j],
                cellR.E[:, j],
                cellR.B[:, j],
                cellRR.E[:, j],
                cellRR.B[:, j],
                cellL.ϕ[j],
                cellR.ϕ[j],
                cellL.ψ[j],
                cellR.ψ[j],
                cellL.dx,
                cellR.dx,
                KS.gas.Ap,
                KS.gas.An,
                KS.gas.D,
                KS.gas.sol,
                KS.gas.χ,
                KS.gas.ν,
                dt,
            )
        end

    elseif uq.method == "galerkin"

        ELL = chaos_ran(cellLL.E, 2, uq)
        BLL = chaos_ran(cellLL.B, 2, uq)
        EL = chaos_ran(cellL.E, 2, uq)
        BL = chaos_ran(cellL.B, 2, uq)
        ER = chaos_ran(cellR.E, 2, uq)
        BR = chaos_ran(cellR.B, 2, uq)
        ERR = chaos_ran(cellRR.E, 2, uq)
        BRR = chaos_ran(cellRR.B, 2, uq)
        ϕL = chaos_ran(cellL.ϕ, uq)
        ϕR = chaos_ran(cellR.ϕ, uq)
        ψL = chaos_ran(cellL.ψ, uq)
        ψR = chaos_ran(cellR.ψ, uq)

        femLRan = zeros(8, uq.op.quad.Nquad)
        femRRan = similar(femLRan)
        for j = 1:uq.op.quad.Nquad
            femL = @view femLRan[:, j]
            femR = @view femRRan[:, j]
            flux_em!(
                femL,
                femR,
                ELL[:, j],
                BLL[:, j],
                EL[:, j],
                BL[:, j],
                ER[:, j],
                BR[:, j],
                ERR[:, j],
                BRR[:, j],
                ϕL[j],
                ϕR[j],
                ψL[j],
                ψR[j],
                cellL.dx,
                cellR.dx,
                KS.gas.Ap,
                KS.gas.An,
                KS.gas.D,
                KS.gas.sol,
                KS.gas.χ,
                KS.gas.ν,
                dt,
            )
        end

        face.femL .= ran_chaos(femLRan, 2, uq)
        face.femR .= ran_chaos(femRRan, 2, uq)

    end

end


text:
using Libdl
const shared_lib = "_build/default/test/ocaml_timens.so"

function start_ocaml()
    lib = Libdl.dlopen(shared_lib)
    ccall(("ocaml_jl_start", shared_lib), Cvoid, ())
end

start_ocaml()

now = Time_ns.now()
println(now)
now_str = Time_ns.to_string(now)
println("now: $now, now_str: $now_str")

span = Time_ns.span_of_string("4m30s")
time = Time_ns.add(now, span)
time_str = Time_ns.to_string(time)
println("$time $time_str")

date = Time_ns.date_of_string("2020-01-16")
ofday = Time_ns.ofday_of_string("13:37")
println(Time_ns.of_date_ofday(date, ofday, "ldn"))

d1 = Time_ns.date_of_string("2020-01-16")
d2 = Time_ns.date_of_string("2020-01-23")
println(Time_ns.weekdays_between(d1, d2))

using InteractiveUtils
println(InteractiveUtils.varinfo())
println(InteractiveUtils.varinfo(Time_ns))
println(Time_ns.diff(time, now))


text: struct T a ;; b ; ; ; ; ;; c end

max_stars_repo_name: gabriel-doriath-dohler/pjulia

max_issues_repo_name: gabriel-doriath-dohler/pjulia

max_forks_repo_name: gabriel-doriath-dohler/pjulia


text:
# Run vic for all watersheds and resolutions

using IcanProj

opt = get_options()

path_sim = opt["target_folder"]

watersheds = opt["stat_sel"]

resolutions = opt["resolutions"]

for watershed in watersheds

    resolutions = ["1km", "5km", "10km", "25km", "50km"]

    for resolution in resolutions

        info("Running vic for $(watershed) at $(resolution) resolution")

        run(`/felles/jmg/VIC.4.2.d/src/./vicNl -g $(joinpath(path_sim, watershed, resolution, "params/global_param"))`)

    end

end


text:
# Adding new Agents

using MAB
using PyPlot
using Printf
import MAB.Algorithms: BanditAlgorithmBase, get_arm_index, update_reward!, reset!, info_str

# ------------------------------------------------------------------------------
struct MyAwesomeAlgorithm <: BanditAlgorithmBase
    noOfArms::Int64
    noOfSteps::Int64
    lastPlayedArm::Int64

    function MyAwesomeAlgorithm( noOfArms::Int64 )
        new( noOfArms,
             0,
             0
        )
    end
end
function get_arm_index( agent::MyAwesomeAlgorithm )
    return rand( 1:agent.noOfArms )
end
function update_reward!( agent::MyAwesomeAlgorithm, r::Real )
    # Do nothing
    nothing
end
function reset!( agent::MyAwesomeAlgorithm )
    # Do nothing
    nothing
end
function info_str( agent::MyAwesomeAlgorithm, latex::Bool )
    return @sprintf( "My Awesome Algorithm" )
end
# ------------------------------------------------------------------------------

bandit = [ Arms.Bernoulli( 0.3 ),
           Arms.Bernoulli( 0.4 ),
           Arms.Bernoulli( 0.5 ) ];

testAlgs = [ epsGreedy( length(bandit), 0.1 ),
             MyAwesomeAlgorithm( length(bandit) ) ];

exp1 = Experiments.Compare( bandit, testAlgs )
# run
noOfRounds      = 1000
noOfTimeSteps   = 1000
result = Experiments.run( exp1, noOfTimeSteps, noOfRounds )

fig = PyPlot.figure()
## Plot avg rewards
for alg in keys(result)
    PyPlot.plot( 1:noOfTimeSteps, cumsum(result[alg], dims = 1)./collect(1:noOfTimeSteps), label = alg )
end

PyPlot.xlabel( "Timesteps" )
PyPlot.ylabel( "Avg. Reward" )
PyPlot.title( "Average Reward (Normalized for $noOfRounds rounds)")
# ax = PyPlot.gca()
# ax[:set_ylim]( [0.00,1.00] )
PyPlot.legend()
PyPlot.grid()
PyPlot.show()


text:
module Logistic

using Test

include("../../example/logistic.jl")

g_result = run_gillespie(MersenneTwister(1), T)[1].n
g_result_record = run_gillespie_record(MersenneTwister(1), T)[1].n
m_result = run_manually(MersenneTwister(1))
m_result_record = run_manually_record(MersenneTwister(1), T)

@test g_result == g_result_record == m_result == m_result_record
e1 = getentries(g_result_record)
e2 = getentries(m_result_record)
@test getts(e1) == getts(e2)
@test getvs(e1) == getvs(e2)

end


text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

module PkgTests

include("pkg.jl")
include("resolve.jl")

end # module

max_stars_repo_name: greimel/julia

max_issues_repo_name: greimel/julia

max_forks_repo_name: greimel/julia