text:
using StatsBase, Random, NSGAII

# include("timeseries.jl")

import Base: copyto!, isequal, iterate, getindex, length, ndims, size

# Abstract operator type.
abstract type AbstractOperator end

# Abstract unary operator type.
abstract type AbstractUnaryOperator                 <: AbstractOperator end
# Abstract binary operator type.
abstract type AbstractBinaryOperator                <: AbstractOperator end

# Abstract unary modal operator type.
abstract type AbstractUnaryModalOperator            <: AbstractUnaryOperator end

# Abstract binary boolean operator type.
abstract type AbstractBinaryBooleanOperator         <: AbstractBinaryOperator end

# Abstract unary interval operator type.
abstract type AbstractUnaryIntervalOperator         <: AbstractUnaryModalOperator end

# Abstract existential (unary) interval operator type.
abstract type AbstractExistentialIntervalOperator   <: AbstractUnaryIntervalOperator end
# Abstract universal (unary) interval operator type.
abstract type AbstractUniversalIntervalOperator     <: AbstractUnaryIntervalOperator end

# Concrete existential (unary) interval operator types.
struct ExistentialGlobally          <: AbstractExistentialIntervalOperator end
struct ExistentialLater             <: AbstractExistentialIntervalOperator end
struct ExistentialAfter             <: AbstractExistentialIntervalOperator end
struct ExistentialOverlaps          <: AbstractExistentialIntervalOperator end
struct ExistentialEnds              <: AbstractExistentialIntervalOperator end
struct ExistentialDuring            <: AbstractExistentialIntervalOperator end
struct ExistentialBegins            <: AbstractExistentialIntervalOperator end
struct ExistentialInverseLater      <: AbstractExistentialIntervalOperator end
struct ExistentialInverseAfter      <: AbstractExistentialIntervalOperator end
struct ExistentialInverseOverlaps   <: AbstractExistentialIntervalOperator end
struct ExistentialInverseEnds       <: AbstractExistentialIntervalOperator end
struct ExistentialInverseDuring     <: AbstractExistentialIntervalOperator end
struct ExistentialInverseBegins     <: AbstractExistentialIntervalOperator end
# Concrete universal (unary) interval operator types.
struct UniversalGlobally            <: AbstractUniversalIntervalOperator end
struct UniversalLater               <: AbstractUniversalIntervalOperator end
struct UniversalAfter               <: AbstractUniversalIntervalOperator end
struct UniversalOverlaps            <: AbstractUniversalIntervalOperator end
struct UniversalEnds                <: AbstractUniversalIntervalOperator end
struct UniversalDuring              <: AbstractUniversalIntervalOperator end
struct UniversalBegins              <: AbstractUniversalIntervalOperator end
struct UniversalInverseLater        <: AbstractUniversalIntervalOperator end
struct UniversalInverseAfter        <: AbstractUniversalIntervalOperator end
struct UniversalInverseOverlaps     <: AbstractUniversalIntervalOperator end
struct UniversalInverseEnds         <: AbstractUniversalIntervalOperator end
struct UniversalInverseDuring       <: AbstractUniversalIntervalOperator end
struct UniversalInverseBegins       <: AbstractUniversalIntervalOperator end

# abstract type AbstractBound end

# struct Top      <: AbstractBound end
# struct Bottom   <: AbstractBound end

# Concrete (binary) conjunction type.
struct Conjunction  <: AbstractBinaryBooleanOperator end
# Concrete (binary) disjunction type.
struct Disjunction  <: AbstractBinaryBooleanOperator end
# Concrete (binary) implication type.
struct Implication  <: AbstractBinaryBooleanOperator end

# Constant existential singletons.
const exG = ExistentialGlobally()
const exL = ExistentialLater()
const exA = ExistentialAfter()
const exO = ExistentialOverlaps()
const exE = ExistentialEnds()
const exD = ExistentialDuring()
const exB = ExistentialBegins()
const exL̄ = ExistentialInverseLater()
const exĀ = ExistentialInverseAfter()
const exŌ = ExistentialInverseOverlaps()
const exĒ = ExistentialInverseEnds()
const exD̄ = ExistentialInverseDuring()
const exB̄ = ExistentialInverseBegins()
# Constant universal singletons.
const univG = UniversalGlobally()
const univL = UniversalLater()
const univA = UniversalAfter()
const univO = UniversalOverlaps()
const univE = UniversalEnds()
const univD = UniversalDuring()
const univB = UniversalBegins()
const univL̄ = UniversalInverseLater()
const univĀ = UniversalInverseAfter()
const univŌ = UniversalInverseOverlaps()
const univĒ = UniversalInverseEnds()
const univD̄ = UniversalInverseDuring()
const univB̄ = UniversalInverseBegins()

# const top = Top()
# const bottom = Bottom()

order_relations = [≤, <, ==, >, ≥]
modal_relations = [exL,exA,exO,exE,exD,exB,exL̄,exĀ,exŌ,exĒ,exD̄,exB̄,univL,univA,univO,univE,univD,univB,univL̄,univĀ,univŌ,univĒ,univD̄,univB̄]
granularity_algebra_values = 0.1
algebra_values = [x for x ∈ 0.0:granularity_algebra_values:1.0]
minmd = 1 # max modal depth
maxmd = 2 # max modal depth
minr = 4
maxr = 6
minh = 1 # min horizon
maxh = 6 # max horizon

show(io::IO, ::ExistentialGlobally)        = print(io, "⟨G⟩")
show(io::IO, ::ExistentialLater)           = print(io, "⟨L⟩")
show(io::IO, ::ExistentialAfter)           = print(io, "⟨A⟩")
show(io::IO, ::ExistentialOverlaps)        = print(io, "⟨O⟩")
show(io::IO, ::ExistentialEnds)            = print(io, "⟨E⟩")
show(io::IO, ::ExistentialDuring)          = print(io, "⟨D⟩")
show(io::IO, ::ExistentialBegins)          = print(io, "⟨B⟩")
show(io::IO, ::ExistentialInverseLater)    = print(io, "⟨L̄⟩")
show(io::IO, ::ExistentialInverseAfter)    = print(io, "⟨Ā⟩")
show(io::IO, ::ExistentialInverseOverlaps) = print(io, "⟨Ō⟩")
show(io::IO, ::ExistentialInverseEnds)     = print(io, "⟨Ē⟩")
show(io::IO, ::ExistentialInverseDuring)   = print(io, "⟨D̄⟩")
show(io::IO, ::ExistentialInverseBegins)   = print(io, "⟨B⟩")
show(io::IO, ::UniversalGlobally)          = print(io, "[G]")
show(io::IO, ::UniversalLater)             = print(io, "[L]")
show(io::IO, ::UniversalAfter)             = print(io, "[A]")
show(io::IO, ::UniversalOverlaps)          = print(io, "[O]")
show(io::IO, ::UniversalEnds)              = print(io, "[E]")
show(io::IO, ::UniversalDuring)            = print(io, "[D]")
show(io::IO, ::UniversalBegins)            = print(io, "[B]")
show(io::IO, ::UniversalInverseLater)      = print(io, "[L̄]")
show(io::IO, ::UniversalInverseAfter)      = print(io, "[Ā]")
show(io::IO, ::UniversalInverseOverlaps)   = print(io, "[Ō]")
show(io::IO, ::UniversalInverseEnds)       = print(io, "[Ē]")
show(io::IO, ::UniversalInverseDuring)     = print(io, "[D̄]")
show(io::IO, ::UniversalInverseBegins)     = print(io, "[B̄]")

# Base.show(io::IO, ::Top)    = print("⊤")
# Base.show(io::IO, ::Bottom) = print("⊥")

# Constant conjunction singleton.
const conjunction   = Conjunction()
# Constant disjunction singleton.
const disjunction   = Disjunction()
# Constant implication singleton.
const implication   = Implication()

show(io::IO, ::Conjunction)    = print(io, " ∧ ")
show(io::IO, ::Disjunction)    = print(io, " ∨ ")
show(io::IO, ::Implication)    = print(io, " → ")

abstract type AbstractProposition end

# p = Proposition(1,"≤",10)
mutable struct Proposition <: AbstractProposition
    attribute::Int64
    relation::Function
    constant::Float64
end

show(io::IO, p::Proposition) = print(io, "A", p.attribute, " ", p.relation, " ", p.constant)

abstract type AbstractHeytingAlgebraValue end

mutable struct HeytingAlgebraValue <: AbstractHeytingAlgebraValue
    value::Float64
end

function show(io::IO, v::HeytingAlgebraValue)
    if v.value == 0.0
        print(io, "⊥")
    elseif v.value == 1.0
        print(io, "⊤")
    else
        print(io, v.value)
    end
end

mutable struct Node{T}
    data::T
    parent::Union{Node{AbstractProposition}, Node{AbstractOperator}, Node{AbstractHeytingAlgebraValue}}
    left::Union{Node{AbstractProposition}, Node{AbstractOperator}, Node{AbstractHeytingAlgebraValue}}
    right::Union{Node{AbstractProposition}, Node{AbstractOperator}, Node{AbstractHeytingAlgebraValue}}

    # Root constructor.
    Node{T}(data) where T = new{T}(data)
    # Child node constructor.
    # Node{T}(data, parent) where T = new{T}(data, parent)
end

parent!(n::Node, p::Node)       = n.parent  = p
leftchild!(n::Node, l::Node)    = n.left    = l
rightchild!(n::Node, r::Node)   = n.right   = r

abstract type AbstractRule end

mutable struct ClassificationRule <: AbstractRule
    antecedent::Node
    consequent::String
end

antecedent(ρ::ClassificationRule) = ρ.antecedent
consequent(ρ::ClassificationRule) = ρ.consequent

function size(ρ::ClassificationRule)
    return _size(antecedent(ρ))
end

function _size(n::Node)
    szl = isdefined(n, :left) ? _size(n.left) : 0
    szr = isdefined(n, :right) ? _size(n.right) : 0
    if typeof(n.data) <: Union{AbstractProposition, AbstractHeytingAlgebraValue}
        return 1 + szl + szr
    else
        return 2 + szl + szr
    end
end

function upwards_modal_depth(n::Node)
    md = isdefined(n, :parent) ? upwards_modal_depth(n.parent) : 0
    md += typeof(n.data) <: AbstractUnaryIntervalOperator ? 1 : 0
    return md
end

function is_leaf(n::Node)
    return (!isdefined(n, :left) && !isdefined(n, :right) ? true : false)
end

function is_internal_node(n::Node)
    return (!is_leaf(n) ? true : false)
end

show(io::IO, ρ::ClassificationRule) = print_rule(io, ρ)

mutable struct ClassificationRules
    rules::Vector{ClassificationRule}
    modalities::Vector{AbstractUnaryIntervalOperator}
    horizon::Int # TODO works only for specific functions; for example, in the future, add α and β for sigmoid-like functions

    ClassificationRules(rules;
        modalities::Vector{AbstractUnaryIntervalOperator}=modal_relations,
        horizon::Int=4) = new(rules, modalities, horizon)
end

rules(Γ::ClassificationRules) = Γ.rules
modalities(Γ::ClassificationRules) = Γ.modalities
horizon(Γ::ClassificationRules) = Γ.horizon
# numclasses(crules::ClassificationRules) = crules.numclasses
maxnumrules(Γ::ClassificationRules) = Γ.maxnumrules
getindex(Γ::ClassificationRules, inds...) = getindex(rules(Γ), inds...)
classes(Γ::ClassificationRules) = collect(Set([consequent(ρ) for ρ in Γ]))
complexity(Γ::ClassificationRules) = reduce(+, [size(ρ) for ρ in Γ])
mean_size(Γ::ClassificationRules) = reduce(+,[size(ρ) for ρ in Γ])/length(Γ)

function show(io::IO, Γ::ClassificationRules)
    println(io, "Horizon=", horizon(Γ))
    print_rules(io, Γ)
end

function show(io::IO, n::Node)
    _print_antecedent(io, n)
    println(io)
end

# Defined, otherwise it gives errors
length(crules::ClassificationRules) = length(rules(crules))
iterate(crules::ClassificationRules) = iterate(rules(crules))
iterate(crules::ClassificationRules, i::Int) = iterate(rules(crules), i)
firstindex(Γ::ClassificationRules) = 1
lastindex(Γ::ClassificationRules) = length(Γ)
# ndims(crules::Type{ClassificationRules}) = ndims(rules(crules)) # TODO necessary?
ndims(::Type{ClassificationRules}) = 1
size(crules::ClassificationRules) = (length(crules),)
# copyto!(crules::ClassificationRules, b::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(identity),Tuple{Array{Any,1}}}) = copyto!(rules(crules), b)
copyto!(crules::ClassificationRules, b::Base.Broadcast.Broadcasted) = copyto!(rules(crules), b)

# p = Proposition(1,"≤",10)

# x = Node{AbstractOperator}(exL)
# y = Node{AbstractProposition}(p)

# leftchild!(x,y)

# println(x)

# TODO
#   * la proposizione deve essere calcolata sulla base del dominio dell'attributo i-esimo scelto
# function _rand_proposition(numprops::Int, relations::Array{String,1}, domain::Union{Array{Int,1},Array{Real,1}})
#     Proposition(rand(1:numprops), relations[rand(1:length(relations))],domain[rand(1:length(domain))])
# end

function _rand_proposition(numattributes::Int64, relations::Array{Function, 1}, domains::Array{Array{Float64, N} where N, 1})
    i = rand(1:numattributes)
    return Proposition(i, relations[rand(1:length(relations))], domains[i][rand(1:length(domains[i]))])
end

function _rand_proposition(numattributes::Int64, relations::Array{Function, 1}, domains::Dict{Symbol, Vector{Number}})
    i = rand(1:numattributes)
    return Proposition(i, relations[rand(1:length(relations))], domains[Symbol("A" * string(i))][rand(1:length(domains[Symbol("A" * string(i))]))])
end

function rand_rule(;
        modalities::Vector{AbstractUnaryIntervalOperator},
        minmd::Int64,
        maxmd::Int64,
        isroot::Bool)
    # TODO: mettere a parametro la probabilità di ritornare una proposizione
    antecedent = _rand_antecedent(; modalities=modalities, minmd=minmd, maxmd=maxmd, isroot=true)
    consequent = _rand_consequent(; classes=train.unique_classes) # edu
    return ClassificationRule(antecedent, consequent)
end

function _rand_antecedent(;
        modalities::Vector{AbstractUnaryIntervalOperator},
        minmd,
        maxmd,
        isroot)
    if maxmd == 0 || (rand() <= 0.5 && minmd <= 0)
        case = rand(1:100)
        # proposition with 90% probability
        if case ≤ 90
            return Node{AbstractProposition}(_rand_proposition(length(attributes(train)[1]),order_relations,train.domains[1])) # TODO works only for temporal frames, i.e. [1]
        # heyting algebra value with 10% probability
        else
            return Node{AbstractHeytingAlgebraValue}(HeytingAlgebraValue(algebra_values[rand(1:length(algebra_values))]))
        end
    else
        root = isroot ? Node{AbstractOperator}([exG, univG][rand(1:2)]) : Node{AbstractOperator}(modalities[rand(1:length(modalities))])
        # root = Node{AbstractOperator}(modalities[rand(1:length(modalities))])
        left = _rand_antecedent(; modalities=modalities, minmd=minmd-1, maxmd=maxmd-1, isroot=false)
        right = _rand_antecedent(; modalities=modalities, minmd=minmd-1, maxmd=maxmd-1, isroot=false)
        leftchild!(root, left)
        rightchild!(root, right)
        parent!(left, root)
        parent!(right, root)
        return root
    end
end

function _rand_consequent(; classes)
    return classes[rand(1:length(classes))]
end

# rules = rand_rules(; numrules=3)
# TODO
# * aggiungere a parametro la profondità modale, modalità (e proposizioni?) -- fatto
# * aggiungere la possibilità di avere solo esistenziali o universali; se chiamo con rand_rules(modalities=[exL]) da errore, ad esempio
# * togliere maxnumrules perché lo vado a catturare con un vincolo quando definisco il problema?
function rand_rules(;
        modalities::Vector{AbstractUnaryIntervalOperator}=modal_relations)
    # @assert [exL,univL] ⊆ modalities "both ⟨L⟩ and [L] must be in the set of modalities"
    # @assert numrules ≥ numclasses "there must be at least $numclasses rules; currently there are $numrules rules"
    # @assert maxnumrules ≥ numrules "there must be at most $maxnumrules rules; currently there are $numrules rules (hint: set both `numrules` and `maxnumrules` keyword arguments)"
    #rules = [rand_rule(modalities=modalities, minmd=minmd, maxmd=maxmd, isroot=true) for i ∈ 1:numrules]
    numrules = rand(minr:maxr)
    rules = ClassificationRule[]
    h = rand(minh:maxh)
    for _ ∈ 1:numrules
        push!(rules, rand_rule(modalities=modalities, minmd=minmd, maxmd=rand(minmd:maxmd), isroot=true))
    end
    return ClassificationRules(rules; modalities=modalities, horizon=h)
end

function modal_depth(rule::ClassificationRule)
    return _modal_depth(antecedent(rule))
end

function _modal_depth(node::Node)
    if typeof(node.data) <: AbstractProposition
        return 0
    elseif typeof(node.data) <: AbstractUnaryIntervalOperator # Union{AbstractUniversalIntervalOperator,AbstractExistentialIntervalOperator}
        return 1 + max(_modal_depth(node.left),_modal_depth(node.right))
    end
    return 0
end

function collect_subformulas(rule::ClassificationRule)
    subformulas = Node[]
    _collect_subformulas(antecedent(rule), subformulas)
    return collect(Set(subformulas))
end

function _collect_subformulas(node::Node, subformulas)
    push!(subformulas, node)
    if isdefined(node, :left) && isdefined(node, :right)
        _collect_subformulas(node.left, subformulas)
        _collect_subformulas(node.right, subformulas)
    end
end

function collect_sorted_subformulas(rule::ClassificationRule)
    return sort!(collect_subformulas(rule), by=x -> _size(x), alg=Base.Sort.QuickSort)
end

function collect_nodes(rule::ClassificationRule)
    nodes = Node[]
    _collect_nodes(antecedent(rule), nodes)
    return nodes
end

function _collect_nodes(node::Node, nodes)
    if isdefined(node, :left)
        _collect_nodes(node.left, nodes)
    end
    push!(nodes, node)
    if isdefined(node, :right)
        _collect_nodes(node.right, nodes)
    end
end

function print_rule(io::IO, rule::ClassificationRule)
    _print_antecedent(io, antecedent(rule))
    print(io, " ⟹  ") # TODO
    _print_consequent(io, consequent(rule))
    println(io)
    return
end

function _print_antecedent(io::IO, node::Node)
    if typeof(node.data) <: AbstractUniversalIntervalOperator
        print(io, node.data)
        print(io, "(")
        _print_antecedent(io, node.left)
        print(io, implication)
        _print_antecedent(io, node.right)
        print(io, ")")
        return
    elseif typeof(node.data) <: AbstractExistentialIntervalOperator
        print(io, node.data)
        print(io, "(")
        _print_antecedent(io, node.left)
        print(io, conjunction)
        _print_antecedent(io, node.right)
        print(io, ")")
        return
    elseif typeof(node.data) <: AbstractProposition
        print(io, node.data)
        return
    elseif typeof(node.data) <: AbstractHeytingAlgebraValue
        print(io, node.data)
        return
    else
        error("you should not be here")
    end
end

function _print_consequent(io::IO, class::String)
    print(io, class)
end

function print_rules(io::IO, crules::ClassificationRules)
    for i ∈ 1:length(crules)
        print_rule(io, crules[i])
    end
end

# rules1 = rand_rules(; numrules=2)
# rules2 = rand_rules(; numrules=3)
# rules_crossover!(rules1, rules2)
function rules_crossover!(parentA::ClassificationRules, parentB::ClassificationRules, childA::ClassificationRules, childB::ClassificationRules)

    # Compute random indices i ∈ {1,…,length(parentA)} and j ∈ {1,…,length(parentB)}.
    i = rand(1:length(parentA))
    j = rand(1:length(parentB))
    # Deep copy the parent genes (i.e., classification rules).
    childA = deepcopy(parentA)
    childB = deepcopy(parentB)
    # Put the j-th rule of parentB in the i-th position of childA.
    rules(childA)[i] = rules(parentB)[j]
    # Put the i-th rule of parentA in the j-th position of childB.
    rules(childB)[j] = rules(parentA)[i]

    """
    i = rand(1:length(parentA)-1)
    j = rand(1:length(parentB)-1)
    # parentA[1:i] and parentB[j+1:end]
    rulesA = [deepcopy(parentA[1:i]); deepcopy(parentB[j+1:length(parentB)])]
    # parentA[i+1:end] and parentB[1:j]
    rulesB = [deepcopy(parentA[i+1:length(parentA)]); deepcopy(parentB[1:j])]
    childA = ClassificationRules(rulesA)
    childB = ClassificationRules(rulesB)
    """

    return
end

# TODO:
# SUM = reduce(+,[_size(x) for x ∈ sub])
# W = [1 - _size(x)/SUM for x ∈ sub]
# P = [x/(length(sub)-1) for x ∈ W]

# levels: 40% 40% 20%
#   1) rules level:
#       a) add rule, and
#       b) remove rule
#   2) rule level that replaces a subformula with another subformula
#   4) class level that changes the class
function rules_mutation!(crules::ClassificationRules)
    level = rand(1:100)

    # rules level
    if level ≤ 60
        innerlevel = rand(1:2)
        # add rule
        if innerlevel == 1
            # TODO
            #   * cancellare questo controllo perché lo farò tramite un vincolo
            #if length(crules) < maxr
            push!(rules(crules), rand_rule(; modalities=modalities(crules), minmd=minmd, maxmd=rand(minmd:maxmd), isroot=true))
            return
            #end
                # numrules(crules) = numrules(crules) + 1
            #end
        # remove rule
        elseif innerlevel == 2
            if length(crules) > minr
                deleteat!(rules(crules), rand(1:length(crules)))
                return
            end
        end
    # rule level
    elseif 60 < level && level ≤ 90
        rule = rules(crules)[rand(1:length(crules))]

        """
        subformulas = collect_sorted_subformulas(rule)
        # sum of sizes
        s = reduce(+,[_size(sf) for sf ∈ subformulas])
        # probabilities: the leaves have higher probability than any internal node, and the root has the lowest probability
        w = [1 - _size(sf)/s for sf ∈ subformulas]./(length(subformulas)-1)
        # sample a subformula with the given probabilities
        sf = sample(subformulas, Weights(w))
        """

        nodes = collect_nodes(rule)
        s = reduce(+,[_size(node) for node ∈ nodes])
        w = [1 - _size(node)/s for node ∈ nodes]./(length(nodes)-1)
        sf = StatsBase.sample(nodes, Weights(w))
        #sf = nodes[rand(1:length(nodes))]

        # upwards modal depth of the selected subformula
        umd = upwards_modal_depth(sf)
        # upwards modal depth is the previously computed one if the subformula is a leaf;
        # otherwise, it is minus 1 because we need to replace an internal node which has a modality by definition
        umd = (is_leaf(sf) ? umd : umd-1)
        # new subtree
        subtree = isdefined(sf, :parent) ?
            _rand_antecedent(modalities=modalities(crules),minmd=minmd-umd, maxmd=maxmd-umd, isroot=false) :
            _rand_antecedent(modalities=modalities(crules),minmd=minmd, maxmd=maxmd, isroot=true)
        # set parent node, if exists
        if isdefined(sf, :parent)
            subtree.parent = sf.parent
        end
    # class level
    else
        i = rand(1:length(crules))
        C = train.unique_classes
        # c = rand(1:numclasses(crules))
        c = C[rand(1:length(C))]

        # TODO: farebbe loop infinito..
        while consequent(rules(crules)[i]) == c
            c = C[rand(1:length(C))]
        end

        rules(crules)[i].consequent = c
        return
    end
end

zz(crules::ClassificationRules) = convert(Float64, length(crules)), mean_size(crules)

# julia> result = NSGAII.nsga_max(10, 20, zz, rand_rules, fCV=CV, fcross=rules_crossover!, fmut=rules_mutation!)
# julia> result = NSGAII.nsga_max(10, 50, zz, rand_rules, fCV=CV, fcross=rules_crossover!, fmut=rules_mutation!)
# julia> result = NSGAII.nsga(50, 1000, zz, rand_rules, fcross=rules_crossover!, fmut=rules_mutation!)

# end

Base.:(==)(x::Proposition, y::Proposition) = x.attribute == y.attribute && x.relation == y.relation && x.constant == y.constant
Base.:(==)(x::HeytingAlgebraValue, y::HeytingAlgebraValue) = x.value == y.value
Base.:(==)(x::AbstractUnaryIntervalOperator, y::AbstractUnaryIntervalOperator) = typeof(x) == typeof(y)
Base.:(==)(x::Node, y::Node) = _isequal(x, y)
Base.:(==)(r::ClassificationRule, s::ClassificationRule) = _isequal(antecedent(r), antecedent(s)) && consequent(r) == consequent(s)
function _isequal(x::Node, y::Node)
    if isdefined(x, :left) && isdefined(x, :right) && isdefined(y, :left) && isdefined(y, :right)
        return x.data == y.data && _isequal(x.left, y.left) && _isequal(x.right, y.right)
    else
        return x.data == y.data
    end
end

function Base.:(==)(R::ClassificationRules, S::ClassificationRules)
    if length(rules(R)) == length(rules(S))
        res = true
        SS = Set(rules(S))
        for i ∈ 1:length(rules(R))
            (!(R[i] ∈ S)) && (res = false)
        end
        # (Set(rules(R)) != Set(rules(S))) && (res = false)
        (classes(R) != classes(S)) && (res = false)
        return res
    else
        return false
    end
end

hash(p::Proposition) = hash(p.attribute) + hash(p.relation) + hash(p.constant)
hash(v::HeytingAlgebraValue) = hash(v.value)
function hash(x::Node)
    if isdefined(x, :left) && isdefined(x, :right)
        return hash(x.data) + hash(x.left) + hash(x.right)
    else
        return hash(x.data)
    end
end
hash(r::ClassificationRule) = hash(antecedent(r)) + hash(consequent(r))
hash(R::ClassificationRules) = reduce(+, [hash(r) for r ∈ rules(R)])

# vuole la proposizione che ha un attributo e la serie di quel attributo
function f̃(p::Proposition, vals::Array{Union{Missing, Float64},1})
    return sum(map(x -> p.relation(x, p.constant), vals))/length(vals)
    #return length([val for val ∈ vals[p.attribute] if p.relation(val, p.constant)])/length(vals[p.attribute])
end

function f̃(p::Proposition, vals::Vector{Float64})
    return sum(map(x -> p.relation(x, p.constant), vals))/length(vals)
    #return length([val for val ∈ vals[p.attribute] if p.relation(val, p.constant)])/length(vals[p.attribute])
end

function ==̃ₕ(x::Int64, y::Int64; horizon::Int64=4)
    # |x-y| ≥ h
    if abs(x-y) ≥ horizon
        return float(0)
    # |x-y| < h
    else
        return (horizon - abs(x-y))/horizon
    end
end

function <̃ₕ(x::Int64, y::Int64; horizon::Int64=4)
    # y-x > h
    if y-x > horizon
        return float(1)
    # y ≦ x
    elseif y ≤ x
        return float(0)
    # y-x ≦ h
    elseif y-x ≤ horizon
        return (y-x)/horizon
    end
end

# ℋ = ⟨H, ∩, ∪, ↪, 0, 1⟩
∩(args...) = min(args...)
∪(args...) = max(args...)
(↪)(a::Float64, b::Float64) = a ≤ b ? float(1) : b

# w₁ = (x, y) and w₂ = (w, z)
function R̃ₓ(rel::AbstractUnaryIntervalOperator, w₁::NTuple{2, Int64}, w₂::NTuple{2, Int64}; horizon::Int64=4)
    x, y, w, z = w₁[1], w₁[2], w₂[1], w₂[2]
    # relations
    if typeof(rel) <: Union{ExistentialLater, UniversalLater}
        return <̃ₕ(y, w; horizon)
    elseif typeof(rel) <: Union{ExistentialAfter, UniversalAfter}
        return ==̃ₕ(y, w; horizon)
    elseif typeof(rel) <: Union{ExistentialOverlaps, UniversalOverlaps}
        return ∩(<̃ₕ(x, w; horizon), <̃ₕ(w, y; horizon), <̃ₕ(y, z; horizon))
    elseif typeof(rel) <: Union{ExistentialEnds, UniversalEnds}
        return ∩(<̃ₕ(x, w; horizon), ==̃ₕ(y, z; horizon))
    elseif typeof(rel) <: Union{ExistentialDuring, UniversalDuring}
        return ∩(<̃ₕ(x, w; horizon), <̃ₕ(z, y; horizon))
    elseif typeof(rel) <: Union{ExistentialBegins, UniversalBegins}
        return ∩(==̃ₕ(x, w; horizon), <̃ₕ(z, y; horizon))
    # inverse relations
    elseif typeof(rel) <: Union{ExistentialInverseLater, UniversalInverseLater}
        return <̃ₕ(z, x; horizon)
    elseif typeof(rel) <: Union{ExistentialInverseAfter, UniversalInverseAfter}
        return ==̃ₕ(z, x; horizon)
    elseif typeof(rel) <: Union{ExistentialInverseOverlaps, UniversalInverseOverlaps}
        return ∩(<̃ₕ(w, x; horizon), <̃ₕ(x, z; horizon), <̃ₕ(z, y; horizon))
    elseif typeof(rel) <: Union{ExistentialInverseEnds, UniversalInverseEnds}
        return ∩(<̃ₕ(w, x; horizon), ==̃ₕ(y, z; horizon))
    elseif typeof(rel) <: Union{ExistentialInverseDuring, UniversalInverseDuring}
        return ∩(<̃ₕ(w, x; horizon), <̃ₕ(y, z; horizon))
    elseif typeof(rel) <: Union{ExistentialInverseBegins, UniversalInverseBegins}
        return ∩(==̃ₕ(x, w; horizon), <̃ₕ(y, z; horizon))
    end
end

hash(x::Tuple{Node, Tuple{Int64, Int64}}) = hash(x[1]) + hash(x[2][1]) + hash(x[2][2])

global H = Dict{Node, Dict{ModalInstance, Dict{NTuple{2,Int}, Float64}}}()

function mc(I::ModalInstance, φ::ClassificationRule; horizon::Int=4, memo::Bool=false)
    if !memo
        return _mc(I,φ; horizon)
    else
        return _mc(I,φ,H; horizon)
    end
end

function _mc(I::ModalInstance, φ::ClassificationRule, H::Dict{Node, Dict{ModalInstance, Dict{NTuple{2,Int}, Float64}}}; horizon::Int=4)

    if haskey(H, antecedent(φ)) && haskey(H[antecedent(φ)], I)
        return H[antecedent(φ)][I][(1,2)]
    end

    sub = collect_sorted_subformulas(φ)
    # L = Dict{Tuple{Union{Node{AbstractOperator}, Node{AbstractProposition}, Node{AbstractHeytingAlgebraValue}},NTuple{2,Int64}},Float64}()
    N = length(I, 1)  # TODO works only on the first (1) frame, i.e., time series
    intervals = [(x,y) for x in 1:N for y in 1:N if x < y]
    for ψ ∈ sub

        if haskey(H, ψ) && haskey(H[ψ],I)
            continue
        end

        if !haskey(H, ψ)
            H[ψ] = Dict{ModalInstance, Dict{NTuple{2,Int}, Float64}}()
            H[ψ][I] = Dict{NTuple{2,Int}, Float64}()
        else
            if !haskey(H[ψ], I)
                H[ψ][I] = Dict{NTuple{2,Int}, Float64}()
            end
        end

        if typeof(ψ.data) <: AbstractProposition
            if length(H[ψ][I]) == 0
                for (x, y) ∈ intervals
                    # if !haskey(H[ψ][I], (x, y))
                    H[ψ][I][(x,y)] = f̃(ψ.data, I[1][ψ.data.attribute][x:y]) # TODO works only for time series
                    # end
                end
            end

        elseif typeof(ψ.data) <: AbstractHeytingAlgebraValue
            if length(H[ψ][I]) == 0
                for (x, y) ∈ intervals
                    H[ψ][I][(x,y)] = ψ.data.value
                end
            end

        elseif typeof(ψ.data) == ExistentialGlobally
            S = Float64[]
            for op in [exL,exA,exO,exE,exD,exB,exL̄,exĀ,exŌ,exĒ,exD̄,exB̄]
                for (x, y) ∈ intervals
                    s = 0.0
                    for (w, z) ∈ intervals
                        # if !haskey(H[ψ][I], (w, z))
                        s = ∪(s, ∩(R̃ₓ(op, (x, y), (w, z)), ∩(H[ψ.left][I][(w,z)], H[ψ.right][I][(w,z)])))
                        # end
                    end
                    push!(S, s)
                end
            end
            H[ψ][I][(1,2)] = ∪(S...)
            return H[ψ][I][(1,2)]

        elseif typeof(ψ.data) == UniversalGlobally
            S = Float64[]
            for op in [univL,univA,univO,univE,univD,univB,univL̄,univĀ,univŌ,univĒ,univD̄,univB̄]
                for (x, y) ∈ intervals
                    s = 1.0
                    for (w, z) ∈ intervals
                        # if !haskey(H[ψ][I], (w, z))
                        s = ∩(s, ↪(R̃ₓ(op, (x, y), (w, z)), ↪(H[ψ.left][I][(w,z)], H[ψ.right][I][(w,z)])))
                        # end
                    end
                    push!(S, s)
                end
            end
            H[ψ][I][(1,2)] = ∩(S...)
            return H[ψ][I][(1,2)]

        elseif typeof(ψ.data) <: AbstractExistentialIntervalOperator
            if length(H[ψ][I]) == 0
                for (x, y) ∈ intervals
                    # if !haskey(H[ψ][I], (x,y))
                    s = 0.0
                    for (w, z) ∈ intervals
                        # if !haskey(H[ψ][I], (w, z))
                        s = ∪(s, ∩(R̃ₓ(ψ.data, (x, y), (w, z)), ∩(H[ψ.left][I][(w,z)], H[ψ.right][I][(w,z)])))
                        # end
                    end
                    H[ψ][I][(x,y)] = s
                    # end
                end
            end

        elseif typeof(ψ.data) <: AbstractUniversalIntervalOperator
            if length(H[ψ][I]) == 0
                for (x, y) ∈ intervals
                    # if !haskey(H[ψ][I], (x,y))
                    s = 1.0
                    for (w, z) ∈ intervals
                        # if !haskey(H[ψ][I], (w, z))
                        s = ∩(s, ↪(R̃ₓ(ψ.data, (x, y), (w, z)), ↪(H[ψ.left][I][(w,z)], H[ψ.right][I][(w,z)])))
                        # end
                    end
                    H[ψ][I][(x,y)] = s
                    # end
                end
            end
        end
    end
    # return 0.0
end

function _mc(I::ModalInstance, φ::ClassificationRule; horizon::Int=4)
    sub = collect_sorted_subformulas(φ)
    L = Dict{Tuple{Union{Node{AbstractOperator}, Node{AbstractProposition}, Node{AbstractHeytingAlgebraValue}},NTuple{2,Int64}},Float64}()
    N = length(I, 1)  # TODO works only on the first (1) frame, i.e., time series
    intervals = [(x,y) for x in 1:N for y in 1:N if x < y]
    for ψ ∈ sub
        if typeof(ψ.data) <: AbstractProposition
            for (x, y) ∈ intervals # setdiff(𝕀, [(-1, 0)])
                # L[(ψ, (x, y))] = ((x, y) != (-1, 0) ? f̃(ψ.data, ts[ψ.data.attribute][x:y]) : 0.0) # TODO is (-1, 0) needed for a proposition? Perhaps not
                L[(ψ, (x ,y))] = f̃(ψ.data, I[1][ψ.data.attribute][x:y]) # TODO works only for time series
            end
        elseif typeof(ψ.data) <: AbstractHeytingAlgebraValue
            for (x, y) ∈ intervals # setdiff(𝕀,[(-1, 0)])
                L[(ψ, (x, y))] = ψ.data.value
            end
        elseif typeof(ψ.data) == ExistentialGlobally
            S = Float64[]
            for op in [exL,exA,exO,exE,exD,exB,exL̄,exĀ,exŌ,exĒ,exD̄,exB̄]
                for (x, y) ∈ intervals
                    s = 0.0
                    for (w, z) ∈ intervals # setdiff(𝕀,[(-1, 0)])
                        s = ∪(s, ∩(R̃ₓ(op, (x, y), (w, z)), ∩(L[(ψ.left, (w, z))], L[(ψ.right, (w, z))])))
                    end
                    push!(S, s)
                end
            end
            return ∪(S...)
        elseif typeof(ψ.data) == UniversalGlobally
            S = Float64[]
            for op in [univL,univA,univO,univE,univD,univB,univL̄,univĀ,univŌ,univĒ,univD̄,univB̄]
                for (x, y) ∈ intervals
                    s = 1.0
                    for (w, z) ∈ intervals # setdiff(𝕀,[(-1, 0)])
                        s = ∩(s, ↪(R̃ₓ(op, (x, y), (w, z)), ↪(L[(ψ.left, (w, z))], L[(ψ.right, (w, z))])))
                    end
                    push!(S, s)
                end
            end
            return ∩(S...)
        elseif typeof(ψ.data) <: AbstractExistentialIntervalOperator
            for (x, y) ∈ intervals # (typeof(ψ.data) === ExistentialLater ? 𝕀 : setdiff(𝕀,[(-1, 0)]))
                s = 0.0
                for (w, z) ∈ intervals # setdiff(𝕀,[(-1, 0)])
                    s = ∪(s, ∩(R̃ₓ(ψ.data, (x, y), (w, z)), ∩(L[(ψ.left, (w, z))], L[(ψ.right, (w, z))])))
                end
                L[(ψ, (x, y))] = s
            end
        elseif typeof(ψ.data) <: AbstractUniversalIntervalOperator
            for (x, y) ∈ intervals # (typeof(ψ.data) === UniversalLater ? 𝕀 : setdiff(𝕀,[(-1,0)]))
                s = 1.0
                for (w, z) ∈ intervals # setdiff(𝕀,[(-1,0)])
                    s = ∩(s, ↪(R̃ₓ(ψ.data, (x, y), (w, z)), ↪(L[(ψ.left, (w, z))], L[(ψ.right, (w, z))])))
                end
                L[(ψ, (x, y))] = s
            end
        end
    end
end

# modal_relations = [exL,exA,exO,exE,exD,exB,exL̄,exĀ,exŌ,exĒ,exD̄,exB̄,univL,univA,univO,univE,univD,univB,univL̄,univĀ,univŌ,univĒ,univD̄,univB̄]

function mmmc(ℐ::ClassificationDataset, Γ::ClassificationRules)
    accuracy = 0.0

    # φ ↦ M ↦ (x, y) ↦ ℝ
    # H = Dict{Node, Dict{ModalInstance, Dict{NTuple{2,Int}, Float64}}}()

    for i in 1:length(ℐ.instances)
        I = ℐ.instances[i]
        class = ℐ.classes[i]
        L = Dict{ClassificationRule, Float64}()

        for ρ in Γ
            L[ρ] = mc(I, ρ; horizon=horizon(Γ), memo=true)
        end

        maxv = argmax(L)
        maxv_rules = [k for (k,v) ∈ L if v == L[maxv]]
        pred = consequent(maxv_rules[rand(1:length(maxv_rules))])

        if pred == class
            accuracy = accuracy + 1.0
        end
    end
    return accuracy/length(ℐ)
end

# function mmmc(𝓣::DataFrame, Γ::ClassificationRules)
#     accuracy = 0.0
#     for T ∈ eachrow(𝓣)
#         L = Dict{ClassificationRule, Float64}()
#         for ρ ∈ Γ
#             L[ρ] = mc(values(T), ρ)
#         end

#         # The key (i.e., rule) with the maximum mapped value.
#         maxv = argmax(L)
#         # The keys (i.e., rules) with the maximum mapped value.
#         maxv_rules = [k for (k,v) ∈ L if v == L[maxv]]
#         # Tights (i.e., more than one rule with the maximum mapped value) are handled randomly.
#         pred = consequent(maxv_rules[rand(1:length(maxv_rules))])

#         if pred == class(T)
#             accuracy = accuracy + 1.0
#         end
#     end
#     return accuracy/nrow(𝓣)
# end

# z(crules::ClassificationRules) = mmmc(instances(td), crules), -1 * mean_size(crules)

function z(crules::ClassificationRules)
    # sizes = [size(rule) for rule ∈ rules(crules)]
    # # max_size = max(sizes...)
    # max_size = 2^(maxdepth+1)-1
    round(mmmc(train, crules), digits=4), round(1/complexity(crules), digits=4) # 1 - sum(sizes)/(max_size*maxr) #1 - sum(sizes)/(max_size*100) # (mean_size(crules)/max_size) * (length(classes(td))/length(rules(crules))) # 1.0 - sum(sizes)/(max_size*12)
end

"""
function CV(crules::ClassificationRules)
    # return length(crules) ≥ numclasses(crules) ? 0 : length(crules)
    return length(classes(td)) - length(classes(crules)) # 1.0 #length(classes(crules)) == length(classes(td)) ? 0 : 1 #length(classes(td)) - length(classes(crules))
end
"""
function CV(crules::ClassificationRules)
    # return length(crules) ≥ numclasses(crules) ? 0 : length(crules)
    # return length(classes(crules)) == length(classes(td)) ? 0.0 : length(classes(td)) - length(classes(crules))
    return abs(length(train.unique_classes) - length(classes(crules)))
end

function init()
    # numrules = rand(minr:maxr)
    # maxmd = rand(2:maxdepth)
    # rand_rules(minmd=2, maxmd=maxdepth)
    rand_rules()
end

function hypervolume_indicator(y::Vector{Tuple{Float64,Float64}}; refpoint=(0,0))
    sort!(y, by=x->x[1], rev=true, alg=QuickSort)

    hi = 0.0
    # (index, tuple)
    for (i, t) in enumerate(y)
        # if it is the first, then
        if i == 1
            hi += abs(t[1] - refpoint[1]) * abs(t[2] - refpoint[2])
        else
            s = y[i-1]
            hi += abs(t[1] - refpoint[1]) * abs(t[2] - s[2])
        end
    end

    return round(hi, digits=4)
end

# init() = rand_rules(numrules=4, maxmd=3)

@time M = nsga_max(6,5,z,init,fcross=rules_crossover!,fmut=rules_mutation!,pmut=0.3)


text:
module PureSeq
using Compat

include("PoissonRegression.jl")
include("ReferenceContigs.jl")
include("BamReader.jl")
include("FeatureMap.jl")
include("ContextMap.jl")
include("DenseBlockIterator.jl")
include("SamWriter.jl")
include("BinningMap.jl")
include("BinnedReader.jl")

end

ext: jl


text:
const VAR_THRESHOLD = -10^-10

function compute_cov_matrix!(
    s::StochGalerkinODE,
    c::StochGalerkinODECache,
    matrix_cache,
    vector_transpose_cache,
    dim_,
    variance_map,
    u,
)
    @unpack indices_polys = s
    @unpack y_hat_for_grid, integral_est = c
    cov_matrix = zeros(eltype(u), dim_, dim_)
    for index_ in indices_polys
        transpose!(vector_transpose_cache, (@view u[:, index_]))
        mul!(matrix_cache, (@view u[:, index_]), vector_transpose_cache)
        cov_matrix .+= matrix_cache .* variance_map[index_]
    end
    return cov_matrix
end

function compute_expectation_and_diag_variance(s::StochGalerkinODE, interval_t, sol_u)
    c = StochGalerkinODECache(s, first(sol_u))
    @unpack dim_, num_polys, indices_polys, poly_basis, grid, normalization_map = s
    @unpack quads, quad_indices = grid
    uType = eltype(eltype(sol_u))
    # stores expectation for each polynomial with a given multi-index
    expectation_map = zeros(uType, num_polys)
    # stores variance for each polynomial with a given multi-index
    variance_map = zeros(uType, num_polys)
    # normalization constant (quadrature weights don't include constant factors from pdf's)
    norm_const = mapreduce(
        index_ -> mapreduce(i -> quads[i].weights[index_[i]], *, 1:length(index_)),
        +,
        quad_indices,
    )
    for index in indices_polys
        expectation_map[index] =
            mapreduce(
                i -> dot(
                    quads[i].weights,
                    (x -> poly_basis[i](x, index[i] - 1)).(quads[i].nodes),
                ),
                *,
                Base.OneTo(length(index)),
            ) / norm_const
        variance = normalization_map[index] / norm_const - expectation_map[index]^2
        # Hack for handling very small (absolute val < 10^-10) and negative variances
        variance >= VAR_THRESHOLD ? variance_map[index] = abs(variance) :
        throw("Variance is negative and has absolute value larger than VAR_THRESHOLD")
    end
    # pre-allocated caches
    matrix_cache = zeros(uType, dim_, dim_)
    vector_transpose_cache = zeros(uType, 1, dim_)
    # arrays for plotting
    expectations = []
    cov_matrices = []
    for i in Base.OneTo(length(interval_t))
        push!(
            expectations,
            mapreduce(
                index -> (@view sol_u[i][:, index]) .* expectation_map[index],
                +,
                indices_polys,
            ),
        )
        push!(
            cov_matrices,
            compute_cov_matrix!(
                s,
                c,
                matrix_cache,
                vector_transpose_cache,
                dim_,
                variance_map,
                sol_u[i],
            ),
        )
    end
    # variances --> from diagonal of cov matrix
    return expectations, diag.(cov_matrices)
end

function plot_with_plus_minus_std(
    s::StochGalerkinODE,
    interval_t,
    sol;
    display_plot = false,
)
    @unpack dim_ = s
    sol_u = [sol(t) for t in interval_t]
    expectations, variances = compute_expectation_and_diag_variance(s, interval_t, sol_u)
    lower = expectations .- (v -> sqrt.(v)).(variances)
    upper = expectations .+ (v -> sqrt.(v)).(variances)
    # initialized plot which will be mutated later
    pl = plot(; size = (500, 400))
    results = (lower, expectations, upper)
    colors = [:blue, :green, :red]
    labels = [
        L"\overline{u}(t) - \sqrt{diag(\Sigma(t))}",
        L"\overline{u}(t)",
        L"\overline{u}(t) + \sqrt{diag(\Sigma(t))}",
    ]
    for i in Base.OneTo(length(results))
        result = results[i]
        color = colors[i]
        for j in Base.OneTo(dim_)
            # put label only once
            label = j == 1 ? labels[i] : nothing
            plot!(
                pl,
                interval_t,
                (r -> getindex(r, j)).(result),
                color = color,
                label = label,
                legend = :outertopright,
            )
        end
    end
    xlabel!(L"t")
    ylabel!(L"u(t)")
    display_plot && display(pl)
    return pl
end

function compute_expected_variance_exluding_one_variable!(
    s::StochGalerkinODE,
    variance_quad_index_cache,
    variance_index_cache,
    poly_prod,
    u_,
    sz_others,
    variable_index,
)
    @unpack dim_, num_polys, poly_basis, grid = s
    @unpack quads = grid
    uType = eltype(u_)
    num_vars = length(num_polys)
    # number of polynomials for the dimension corresponding to "variable_index"
    num_polys_var_index_dim = num_polys[variable_index]
    # map j -> Var_(xi)[ψ^(i)_{j}(xi)], 1 <= j <= num_polys_var_index_dim, where ψ^(i) is the orthogonal
    #  polynomial family on the dimension corresponding to "variance_index"
    variance_var_index_poly_family_map = zeros(uType, num_polys[variable_index])
    # normalization constant considering distribution of the variable on the "variable_index" dimension
    # (quadrature weights don't include constant factors from pdf's)
    norm_const_var_index = mapreduce(
        j -> quads[variable_index].weights[j],
        +,
        Base.OneTo(num_polys_var_index_dim),
    )
    for j in Base.OneTo(num_polys_var_index_dim)
        variance_var_index_jth_poly =
        # First term is E_{xi}[(ψ^{i}_{j}(xi))^2]
            dot(
                quads[variable_index].weights,
                (x -> poly_basis[variable_index](x, j - 1)^2).(quads[variable_index].nodes),
            ) / norm_const_var_index -
            # Second term is (E_{xi}[ψ^{i}_{j}(xi)])^2
            (
                dot(
                    quads[variable_index].weights,
                    (
                        x -> poly_basis[variable_index](x, j - 1)
                    ).(quads[variable_index].nodes),
                ) / norm_const_var_index
            )^2
        variance_var_index_poly_family_map[j] = variance_var_index_jth_poly
    end
    # helper funcion to shift all indices greater than variable_index one position to the left
    shift_index = j -> (j < variable_index) ? j : j - 1
    running_sum_expectation_of_variance = zeros(uType, dim_)
    # normalization constant considering distribution of other vars
    # (quadrature weights don't include constant factors from pdf's)
    norm_const_other_vars = zero(uType)
    @inbounds for quad_index in CartesianIndices(sz_others)
        fill!(variance_quad_index_cache, zero(uType))
        # computes product of weights at the position determined by "quad_index"
        prod_weights = one(uType)
        @inbounds for j in Base.OneTo(num_vars)
            @unpack weights = quads[j]
            if j != variable_index
                prod_weights *= weights[quad_index[shift_index(j)]]
            end
        end
        norm_const_other_vars += prod_weights
        # pre-compute product of polynomials of multi-index "index" at the value determined by "quad_index"
        @inbounds for index in CartesianIndices(sz_others)
            poly_prod[index] = one(uType)
            for j in Base.OneTo(num_vars)
                @unpack nodes = quads[j]
                if j != variable_index
                    poly_prod[index] *= poly_basis[j](
                        nodes[quad_index[shift_index(j)]],
                        index[shift_index(j)] - 1,
                    )
                end
            end
        end
        # now compute variance considering other variables
        # we use the following identities in the loop below (note that polynomials of different indices are uncorrelated and i = variable_index,
        # to make the notation easier)
        # Y = ∑_{j <= num_polys_i}[(∑_{index_} [C{join_index(i, index_)} * ψ_{index_}(x~i)]) * ψ^{i}_{j}(xi)]
        # --> Var_{xi}(Y|x~i) = ∑_{j <= num_polys_i}[(∑_{index_} [C{join_index(i, index_)} * ψ_{index_}(x~i)])^2 * var_{xi}(ψ^{i}_{j}(xi))]
        # where index_ spans over CartesianIndices(sz_others) (the number of polynomials in the other dimensions)
        @inbounds for j in Base.OneTo(num_polys_var_index_dim)
            # variance_index_cache receives the term ∑_{index_} [C{join_index(i, index_)} * ψ_{index_}(x~i)]
            fill!(variance_index_cache, zero(uType))
            @inbounds for index_ in CartesianIndices(sz_others)
                variance_index_cache .+= (@view u_[:, j, index_]) .* poly_prod[index_]
            end
            # now that we have ∑_{index_} [C{join_index(i, index_)} * ψ_{index_}(x~i)],
            # compute (∑_{index_} [C{join_index(i, index_)} * ψ_{index_}(x~i)])^2 * var_{xi}(ψ^{i}_{j}(xi))
            # and add to the running sum stored in "variance_quad_index_cache"
            variance_quad_index_cache .+=
                variance_index_cache .^ 2 .* (variance_var_index_poly_family_map[j])
        end
        # now that we have, ∑_{j <= num_polys_i}[(∑_{index_} [C{join_index(i, index_)} * ψ_{index_}(x~i)])^2 * var_{xi}(ψ^{i}_{j}(xi))]
        # multiply by the product of weights (excluding the quadrature on the "variable_index" dimension) and add
        # to the running sum of the expectation of the variance to compute the outer integral (with respect to x~i)
        running_sum_expectation_of_variance .+= variance_quad_index_cache .* prod_weights
    end
    # finally, normalize (norm_const_other_vars is just the sum of the product of weights excluding
    # the quadrature on the "variable_index" dimension)
    running_sum_expectation_of_variance ./= norm_const_other_vars
    return running_sum_expectation_of_variance
end

function compute_total_order_sobol_indices(
    s::StochGalerkinODE,
    sol,
    interval_t,
    variable_index,
)
    sol_u = [sol(t) for t in interval_t]
    c = StochGalerkinODECache(s, first(sol_u))
    @unpack dim_, num_polys, indices_polys, poly_basis, grid = s
    @unpack quads, quad_indices = grid
    uType = eltype(eltype(sol_u))
    num_vars = length(num_polys)
    # number of polys for all variables except for the one we are computing the Sobol index
    sz_others =
        Tuple(num_polys[i] for i in Base.OneTo(length(num_polys)) if i != variable_index)
    # stores E_{x~i}[Var_{xi}(y|x~i)]
    var_i = []
    # pre-allocated caches
    variance_quad_index_cache = zeros(uType, dim_)
    variance_index_cache = zeros(uType, dim_)
    poly_prod = zeros(uType, sz_others)
    # dimension's permutation
    perm =
        (1, variable_index + 1, (i for i in 2:(num_vars+1) if i != (variable_index + 1))...)
    for u in sol_u
        # permute dimensions to not create an extra CartesianIndex during the update
        # of "variance_index_cache" (line 211) in the loop of the function above, reducing
        # allocations in this way
        u_ = PermutedDimsArray(u, perm)
        push!(
            var_i,
            compute_expected_variance_exluding_one_variable!(
                s,
                variance_quad_index_cache,
                variance_index_cache,
                poly_prod,
                u_,
                sz_others,
                variable_index,
            ),
        )
    end
    _, variance = compute_expectation_and_diag_variance(s, interval_t, sol_u)
    return [var_i[j] ./ variance[j] for j in Base.OneTo(length(interval_t))]
end

max_stars_repo_name: d-netto/PolyChaosODE

max_issues_repo_name: d-netto/PolyChaosODE

max_forks_repo_name: d-netto/PolyChaosODE


text:
#!/usr/bin/env julia
using Gtk.ShortNames, Gtk

include("GameOfLife.jl")

const win = GtkWindow("Game of Life")
const hbox = GtkBox(:h)
const board = GtkLabel("")

const buttonbox = GtkBox(:v)
const label = GtkLabel("0 generation")
const reset_button = GtkButton("Reset")
const next_button = GtkButton("Next")

push!(win, hbox)
push!(hbox, board)
push!(hbox, buttonbox)
push!(buttonbox, label)
push!(buttonbox, reset_button)
push!(buttonbox, next_button)

set_gtk_property!(hbox, :expand, board, true)

row, col = 20, 40
d = Gol(row, col)
GAccessor.markup(board, "" * sprint(d) * "")

ngen = 0
function nextstate(x)
    global ngen += 1
    set_gtk_property!(label, :label, "$ngen generation")
    d.state = next_generation(d)
    GAccessor.markup(board, "" * sprint(d) * "")
end

function resetbutton(x, l)
    global ngen = 0
    set_gtk_property!(label, :label, "0 generation")
    set_gtk_property!(l, :label, "")
    global d = Gol(row, col)
    GAccessor.markup(board, "" * sprint(d) * "")
    # set_gtk_property!(l, :label, sprint(d))
    return nothing
end

signal_connect(nextstate, next_button, "clicked")
signal_connect(x -> resetbutton(x, board), reset_button, "clicked")

showall(win)

if !isinteractive()
    c = Condition()
    signal_connect(win, :destroy) do widget
        notify(c)
    end
    wait(c)
end

max_stars_repo_name: goropikari/JuliaGUIAppExample

max_issues_repo_name: goropikari/JuliaGUIAppExample

max_forks_repo_name: goropikari/JuliaGUIAppExample


text:
using Images, Gtk, Reactive, GtkReactive, ImageView
n = 100#1024
img1 = reshape(linspace(Gray{N0f16}(0), Gray{N0f16}(1), n^2), n, n)
img2 = reshape(linspace(Gray{N0f16}(0), Gray{N0f16}(1), n^2), n, n)'
img = colorview(RGB, img1, img1, img2)
g = imshow(img)

img1 .= rand(Gray{N0f16}, n,n)

img1 .= reshape(linspace(Gray{N0f16}(0), Gray{N0f16}(1), n^2), n, n)

a = value(g["roi"]["image roi"])

push!(g["roi"]["redraw"], nothing)

canvas = g["gui"]["canvas"]
s1 = slider(linspace(0,1,2^16), value=1)
s2 = slider(linspace(0,1,2^16), value=1)
img1tmp = similar(img1)
img2tmp = similar(img2)

foreach(s1, s2, init = nothing) do m1, m2
    img1tmp .= min.(img1, m1)
    img2tmp .= min.(img2, m2)
    imshow(canvas, colorview(RGB, img1tmp, img1tmp, img2tmp))
    nothing
end

push!(g["gui"]["vbox"], s1, s2)

showall(g["gui"]["window"])

zr, slicedata = roi(img1)
gd = imshow_gui((n, n), slicedata)
imshow(gd["frame"][1], gd["canvas"][1,1], img1, nothing, zr, slicedata)
imshow(gd["frame"][2], gd["canvas"][1,2], img2, nothing, zr, slicedata)
showall(gd["window"])

gd = imshow_gui((200, 200), slicedata, (1,2))
imshow(gd["frame"][1,1], gd["canvas"][1,1], img1, nothing, zr, slicedata)
imshow(gd["frame"][1,2], gd["canvas"][1,2], mriseg, nothing, zr, slicedata)
showall(gd["window"])

using ImageView, GtkReactive, TestImages, Colors
# Prepare the data
n = 200
mri = reshape(linspace(Gray{N0f16}(0), Gray{N0f16}(1), n^2), n, n)
mriseg = reshape(linspace(Gray{N0f16}(0), Gray{N0f16}(1), n^2), n, n)'
zr, slicedata = roi(mri, (1,2))
gd = imshow_gui((200, 200), slicedata, (1,2))
imshow(gd["frame"][1,1], gd["canvas"][1,1], mri, nothing, zr, slicedata)
imshow(gd["frame"][1,2], gd["canvas"][1,2], mriseg, nothing, zr, slicedata)
showall(gd["window"])


text:
module Extensions

using Compat; import Compat.String

"""
!!summary(Methods to extend how Docile handles parsing of docstrings.)

These methods could just as easily be defined outside of the package and allow
for package authors to customise how their documentation is presented to users.
"""
Extensions

import ..Formats: Formats, @META_str
import ..Cache

"""
!!summary(Get the value stored in an object's metadata field.)

In the following example the value associated with the field ``:author`` is
spliced back into the docstring in place of it:

    \\!!get(author)

When no field is found in the metadata for the object, the module and package
metadata are searched in turn.
"""
function Formats.metamacro(::META"get", body, mod, obj)
    out = Cache.findmeta(mod, obj, symbol(body), Any)
    isnull(out) && throw(KeyError("No metadata found in $(obj) for '$(body)'."))
    get(out)
end

"""
!!summary(Set the value for a field in an object's metadata.)

    \\!!set(author:Author's Name)

The key in this example is ``:author`` and the value is ``"Author's Name"``.
"""
function Formats.metamacro(::META"set", body, mod, obj)
    key, value = @compat(split(body, ':', limit = 2))
    Cache.getmeta(mod, obj)[symbol(key)] = value
    ""
end

function Formats.metamacro(::META"setget", body, mod, obj)
    Base.warn_once("'!!setget(...)' is deprecated. Using '!!var(...)' instead.")
    Formats.metamacro(META"var"(), body, mod, obj)
end

"""
!!summary(Equivalent to ``!!set`` followed by ``!!get`` for the provided key.)

    \\!!var(author:Author's Name)

The key in this example is ``:author`` and the value is ``"Author's Name"``.
"""
function Formats.metamacro(::META"var", body, mod, obj)
    key, value = @compat(split(body, ':', limit = 2))
    Cache.getmeta(mod, obj)[symbol(key)] = value
end

"""
!!summary(Specify a short (120 character) summary for a docstring.)

    \\!!summary(...)

The text will be used in the generated index page produced by Lexicon.

A warning is printed when a summary exceeds the character limit.
"""
function Formats.metamacro(::META"summary", body, mod, obj)
    length(body) > 120 && warn("Overlong summary in '$(obj)' docstring.")
    Cache.getmeta(mod, obj)[:summary] = body
    body
end

"""
!!summary(Make the contained text only appear in non-interactive output.)

    \\!!longform(
    ...
    )

In the REPL the text is not displayed. Other ``metamacro`` calls can be nested
inside a ``\\!!longform(...)`` call, such as ``\\!!include(...)``.
"""
function Formats.metamacro(::META"longform", body, mod, obj)
    body = Formats.extractmeta!(body, mod, obj) # Make nestable.
    Cache.getmeta(mod, obj)[:longform] = body
    isinteractive() ? "" : body
end

"""
!!summary(Splice the contents of a file in place of the ``metamacro`` call.)

    \\!!include(filename)

``filename`` must reference an available file found relative to the source file
where the ``metamacro`` is called from.
"""
function Formats.metamacro(::META"include", body, mod, obj)
    meta = Cache.getmeta(mod, obj)
    filename = abspath(joinpath(dirname(meta[:textsource][2]), body))
    isfile(filename) || throw(ArgumentError("Unknown '!!include(...)' file: $(filename)"))
    Formats.extractmeta!(readall(filename), mod, obj)
end

end


text:
using Oxygen

println("Testing SMILES Parser")

function sameatom(atoms::Tuple{OxygenAtom,OxygenAtom})::Bool
    (a,b) = atoms
    a.number == b.number
end

function sameatoms(a::Array{OxygenAtom,1}, b::Array{OxygenAtom,1})::Bool
    all(map(sameatom, zip(a,b)))
end

@testset "SmilesToMol" begin
    ethyl_acetate = "CC(=O)OCC"
    ethyl_acetate_mol = smilestomol(ethyl_acetate)
    @test typeof(ethyl_acetate_mol) == OxygenMol
    @test sameatoms(ethyl_acetate_mol.atoms, [OxygenAtom("C"), OxygenAtom("C"), OxygenAtom("O"), OxygenAtom("O"), OxygenAtom("C"), OxygenAtom("C")])
    @test ethyl_acetate_mol.adj ==
          [[(2, 1.0)], [(1, 1.0), (3, 2.0), (4, 1.0)], [(2, 2.0)], [(2, 1.0), (5, 1.0)], [(4, 1.0), (6, 1.0)], [(5, 1.0)]]

    benzene = "c1ccccc1"
    benzene_mol = smilestomol(benzene)
    @test typeof(benzene_mol) == OxygenMol
    @test sameatoms(benzene_mol.atoms, [OxygenAtom("C"), OxygenAtom("C"), OxygenAtom("C"), OxygenAtom("C"), OxygenAtom("C"), OxygenAtom("C")])
    @test benzene_mol.adj == [
        [(2, 1.5), (6, 1.5)],
        [(1, 1.5), (3, 1.5)],
        [(2, 1.5), (4, 1.5)],
        [(3, 1.5), (5, 1.5)],
        [(4, 1.5), (6, 1.5)],
        [(5, 1.5), (1, 1.5)],
    ]

    cipro = "C1CC1N2C=C(C(=O)C3=CC(=C(C=C32)N4CCNCC4)F)C(=O)O"
    cipro_mol = smilestomol("C1CC1N2C=C(C(=O)C3=CC(=C(C=C32)N4CCNCC4)F)C(=O)O")
    @test typeof(cipro_mol) == OxygenMol
    @test sameatoms(cipro_mol.atoms[7:11], [OxygenAtom("C"), OxygenAtom("O"), OxygenAtom("C"), OxygenAtom("C"), OxygenAtom("C")])
    @test cipro_mol.adj[7:11] == [
        [(6, 1.0), (8, 2.0), (9, 1.0)],
        [(7, 2.0)],
        [(7, 1.0), (10, 2.0), (14, 1.0)],
        [(9, 2.0), (11, 1.0)],
        [(10, 1.0), (12, 2.0), (21, 1.0)],
    ]
end


text:
export hessian_operator
function hessian_operator(nlp, x)
    n = nlp.meta.nvar
    temp = Array{Float64}(undef, n)
    return hess_op!(nlp, x, temp)
end


text:
module CoolTensors

# credits to @tkf on discourse: https://discourse.julialang.org/t/fun-one-liners/28352/57
@doc let path = joinpath(dirname(@__DIR__), "README.md")
    include_dependency(path)
    open(path) do io
        lines = eachline(io)
        # skip badges in lines 2-6
        s = first(lines) * '\n' * join(Iterators.drop(lines, 5), '\n')
        replace(s, "```julia" => "```jldoctest README")
    end
end
CoolTensors

export Tensor, @T_str, raise, lower, TIndex, TI,
    tbegin, tend

include("tensor.jl")

export TScalar, TVector, TCovector, TLinearMap, TBilinear

const TScalar = Tensor{T,0,T""} where {T}
const TVector = Tensor{T,1,T"'"} where {T}
const TCovector = Tensor{T,1,T","} where {T}
const TLinearMap = Tensor{T,2,T"',"} where {T}
const TBilinear = Tensor{T,2,T",,"} where {T}

include("contractions.jl")
include("tindex.jl")

include("tbeginend.jl")

export ⊗ # from TensorCore.jl

include("operations.jl")

end


text:
type CrestAuthData
	requestState::AbstractString
	server::HttpServer.Server
	authResponse::Dict

	CrestAuthData(requestState::AbstractString) = new(requestState)
end

authorization_received(authData::CrestAuthData) = isdefined(authData, :authResponse)

function server_task(authData::CrestAuthData, req::HttpServer.Request, res::HttpServer.Response)
	resp = HttpServer.Response()
	resp.headers["Connection"] = "close"
	if startswith(req.resource, "/?")
		query = HttpServer.parsequerystring(req.resource[3:end])
		if isa(query, Associative) && get(query, "state", "") == authData.requestState
			authData.authResponse = query
			resp.data = "Authorization data received, thank you"
		end
	elseif req.resource == "/"
		# When we're requesting a token, it arrives in the browser as a fragment that is not sent to our HTTP server
		# So in this case we send a script that will reload the page, forwarding the fragment as a resource
		resp.data =
			"""
			Redirecting authorization fragment to Julia
			<script type="text/javascript">
				if (window.location.hash) {
					var loc = window.location.toString().replace("#", "?")
					window.location.replace(loc)
				}
			</script>
			"""
	end
	return resp
end

function run_server(authData::CrestAuthData, port::UInt16)
	http = HttpServer.HttpHandler((req, res)->server_task(authData, req, res))
	authData.server = HttpServer.Server(http)
	@async run(authData.server; port = port)
end

function stop_server(authData::CrestAuthData)
	close(authData.server)
	yield()
end

function request_access_url(authData::CrestAuthData, appInfo::Dict)
	params = Dict("response_type" => get(appInfo, "secretKey", "") != "" ? "code" : "token",
			  "redirect_uri" => appInfo["callbackURL"],
			  "client_id" => appInfo["clientID"],
			  "scope" => appInfo["scope"],
			  "state" => authData.requestState)
	queryStr = Requests.format_query_str(params)
	return "https://login.eveonline.com/oauth/authorize/?$queryStr"
end

function open_browser(url::AbstractString)
	if is_windows()
		url = replace(url, "&", "^&") # escape & on windows
		run(`cmd /c start $url`)
	else
		spawn(`xdg-open "$url"`)
	end
end

function request_authorization_token(endpoint::AbstractString, appInfo::Dict, code::AbstractString, refresh::Bool)
	authStr = base64encode(appInfo["clientID"] * ":" * appInfo["secretKey"])
	if refresh
		params = Dict("grant_type" => "refresh_token",
				  "refresh_token" => code)
	else
		params = Dict("grant_type" => "authorization_code",
				  "code" => code)
	end
	dataStr = Requests.format_query_str(params)
	resp = Requests.post(endpoint;
	                     data=dataStr,
						 headers=Dict{Any, Any}("Authorization" => "Basic $authStr",
						          "Content-Type" => "application/x-www-form-urlencoded"))
	return JSON.parse(String(resp.data))
end

function request_access(endpoint::AbstractString, appInfo::Dict)
	authFile = joinpath(cacheDir, "authorization.json")
	auth = json_read(authFile)
	authTime = stat(authFile).mtime
	if auth != nothing && time() - authTime <= get(auth, "expires_in", 0) / 2
		# We have an auth token that still has half of its validity period to go
		return auth
	end
	if auth == nothing || !haskey(auth, "refresh_token") || get(appInfo, "secretKey", "") == ""
		authData = CrestAuthData("crestauth.jl$(rand(UInt))")
		uri = URIParser.URI(appInfo["callbackURL"])
		port = uri.port
		if port == 0
			port = uri.schema=="https"? 443 : 80
		end
		run_server(authData, port)
		open_browser(request_access_url(authData, appInfo))
		while !authorization_received(authData)
			yield()
		end
		stop_server(authData)
		if haskey(authData.authResponse, "code")
			auth = request_authorization_token(endpoint, appInfo, authData.authResponse["code"], false)
		else
			auth = Dict{AbstractString, Any}(authData.authResponse)
			auth["expires_in"] = parse(get(auth, "expires_in", "0"))
			delete!(auth, "state")
		end
		json_write(authFile, auth)
	else
		auth = request_authorization_token(endpoint, appInfo, auth["refresh_token"], true)
	end
	return auth
end


text:
# This file was generated by the Julia Swagger Code Generator
# Do not modify this file directly. Modify the swagger specification instead.

mutable struct IoK8sApiStorageV1StorageClass <: SwaggerModel
    allowVolumeExpansion::Any # spec type: Union{ Nothing, Bool } # spec name: allowVolumeExpansion
    allowedTopologies::Any # spec type: Union{ Nothing, Vector{IoK8sApiCoreV1TopologySelectorTerm} } # spec name: allowedTopologies
    apiVersion::Any # spec type: Union{ Nothing, String } # spec name: apiVersion
    kind::Any # spec type: Union{ Nothing, String } # spec name: kind
    metadata::Any # spec type: Union{ Nothing, IoK8sApimachineryPkgApisMetaV1ObjectMeta } # spec name: metadata
    mountOptions::Any # spec type: Union{ Nothing, Vector{String} } # spec name: mountOptions
    parameters::Any # spec type: Union{ Nothing, Dict{String, String} } # spec name: parameters
    provisioner::Any # spec type: Union{ Nothing, String } # spec name: provisioner
    reclaimPolicy::Any # spec type: Union{ Nothing, String } # spec name: reclaimPolicy
    volumeBindingMode::Any # spec type: Union{ Nothing, String } # spec name: volumeBindingMode

    function IoK8sApiStorageV1StorageClass(;allowVolumeExpansion=nothing, allowedTopologies=nothing, apiVersion=nothing, kind=nothing, metadata=nothing, mountOptions=nothing, parameters=nothing, provisioner=nothing, reclaimPolicy=nothing, volumeBindingMode=nothing)
        o = new()
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("allowVolumeExpansion"), allowVolumeExpansion)
        setfield!(o, Symbol("allowVolumeExpansion"), allowVolumeExpansion)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("allowedTopologies"), allowedTopologies)
        setfield!(o, Symbol("allowedTopologies"), allowedTopologies)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("apiVersion"), apiVersion)
        setfield!(o, Symbol("apiVersion"), apiVersion)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("kind"), kind)
        setfield!(o, Symbol("kind"), kind)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("metadata"), metadata)
        setfield!(o, Symbol("metadata"), metadata)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("mountOptions"), mountOptions)
        setfield!(o, Symbol("mountOptions"), mountOptions)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("parameters"), parameters)
        setfield!(o, Symbol("parameters"), parameters)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("provisioner"), provisioner)
        setfield!(o, Symbol("provisioner"), provisioner)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("reclaimPolicy"), reclaimPolicy)
        setfield!(o, Symbol("reclaimPolicy"), reclaimPolicy)
        validate_property(IoK8sApiStorageV1StorageClass, Symbol("volumeBindingMode"), volumeBindingMode)
        setfield!(o, Symbol("volumeBindingMode"), volumeBindingMode)
        o
    end
end # type IoK8sApiStorageV1StorageClass

const _property_map_IoK8sApiStorageV1StorageClass = Dict{Symbol,Symbol}(Symbol("allowVolumeExpansion")=>Symbol("allowVolumeExpansion"), Symbol("allowedTopologies")=>Symbol("allowedTopologies"), Symbol("apiVersion")=>Symbol("apiVersion"), Symbol("kind")=>Symbol("kind"), Symbol("metadata")=>Symbol("metadata"), Symbol("mountOptions")=>Symbol("mountOptions"), Symbol("parameters")=>Symbol("parameters"), Symbol("provisioner")=>Symbol("provisioner"), Symbol("reclaimPolicy")=>Symbol("reclaimPolicy"), Symbol("volumeBindingMode")=>Symbol("volumeBindingMode"))
const _property_types_IoK8sApiStorageV1StorageClass = Dict{Symbol,String}(Symbol("allowVolumeExpansion")=>"Bool", Symbol("allowedTopologies")=>"Vector{IoK8sApiCoreV1TopologySelectorTerm}", Symbol("apiVersion")=>"String", Symbol("kind")=>"String", Symbol("metadata")=>"IoK8sApimachineryPkgApisMetaV1ObjectMeta", Symbol("mountOptions")=>"Vector{String}", Symbol("parameters")=>"Dict{String, String}", Symbol("provisioner")=>"String", Symbol("reclaimPolicy")=>"String", Symbol("volumeBindingMode")=>"String")
Base.propertynames(::Type{ IoK8sApiStorageV1StorageClass }) = collect(keys(_property_map_IoK8sApiStorageV1StorageClass))
Swagger.property_type(::Type{ IoK8sApiStorageV1StorageClass }, name::Symbol) = Union{Nothing,eval(Meta.parse(_property_types_IoK8sApiStorageV1StorageClass[name]))}
Swagger.field_name(::Type{ IoK8sApiStorageV1StorageClass }, property_name::Symbol) =  _property_map_IoK8sApiStorageV1StorageClass[property_name]

function check_required(o::IoK8sApiStorageV1StorageClass)
    (getproperty(o, Symbol("provisioner")) === nothing) && (return false)
    true
end

function validate_property(::Type{ IoK8sApiStorageV1StorageClass }, name::Symbol, val)
end


text:
module Banana
    using DataModel

    export BananaModel

    type BananaModel <: AbstractDataModel
    end

    function DataModel.getgrad(dm::BananaModel;noisevar=0.0)
        # noise variance to simulate noisy gradient.
        function banana_gradient(x)
            @assert length(x) == 2
            n1 = noisevar > 0 ? randn()*sqrt(noisevar) : 0.0
            n2 = noisevar > 0 ? randn()*sqrt(noisevar) : 0.0
            [-1.0/20.0*( -400x[1]*(x[2]-x[1]^2) - 2(1-x[1])) + n1, -1.0/20.0*200*(x[2]-x[1]^2) + n2]
        end
        return banana_gradient
    end

    function DataModel.getllik(dm::BananaModel)
        function banana_logdensity(x)
            @assert length(x) == 2
            -1.0/20.0*(100*(x[2]-x[1]^2)^2 + (1-x[1])^2)
        end
        return banana_logdensity
    end
end


text:
@testset "JS_BWG_HNE_DL" begin
    θ₀ = [0.7, 0.9, 3.3, 5.0, 0.3, 4, 2.7, 0.55, 0.26]
    ω = 1.1
    @testset "Preallocation" begin
        model = JS_BWG_HNE_DL{1,40}(θ₀)
        @test model.r_over4 == model.r/4
        @test model.ωₚ² == model.ωₚ^2
        @test model.ωₚ³ == model.ωₚ^3
        @test model.ωₚ⁴ == model.ωₚ^4
        @test model.ωₚ⁶ == model.ωₚ^6
        @test model.logγ == log(model.γ)
        @test model.σᵣ_over3 == model.σᵣ/3
        @test model.cosϕₘ == cos(model.ϕₘ)
        @test model.sinϕₘ == sin(model.ϕₘ)
        @test model.cos2ϕₘ == cos(2model.ϕₘ)
        @test model.sin2ϕₘ == sin(2model.ϕₘ)
    end
    @testset "Gradient" begin
        @test approx_gradient(θ -> sdf(JS_BWG_HNE_DL{1,40}(θ), ω), θ₀)      ≈ grad_sdf(JS_BWG_HNE_DL{1,40}(θ₀), ω)
        @test approx_gradient(θ -> sdf(JS_BWG_HNE_DL{1,40}(θ), 0), θ₀)      ≈ grad_sdf(JS_BWG_HNE_DL{1,40}(θ₀), 0)
    end
    @testset "Hessian" begin
        @test approx_hessian( θ -> grad_sdf(JS_BWG_HNE_DL{1,40}(θ), ω), θ₀) ≈ hess_sdf(JS_BWG_HNE_DL{1,40}(θ₀), ω)
        @test approx_hessian( θ -> grad_sdf(JS_BWG_HNE_DL{1,40}(θ), 0), θ₀) ≈ hess_sdf(JS_BWG_HNE_DL{1,40}(θ₀), 0)
    end
    @testset "coherancy" begin
        S = sdf(JS_BWG_HNE_DL{1,40}(θ₀), ω)
        @test coherancy(JS_BWG_HNE_DL{1,40}(θ₀), ω) ≈ [S[i,j]/sqrt(S[i,i]*S[j,j]) for i in 1:size(S,1), j in 1:size(S,2)]
    end
    @testset "Error handling" begin
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(-0.7,0.9, 3.3, 5.0, 0, 4, 2.7, 0.55, 0.26)
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(0.7,-0.9, 3.3, 5.0, 0, 4, 2.7, 0.55, 0.26)
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(0.7, 0.9, 0.8, 5.0, 0, 4, 2.7, 0.55, 0.26) # 0.8 <1
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(0.7, 0.9, 3.3, 0.9, 0, 4, 2.7, 0.55, 0.26) # 0.9 < 1
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(0.7, 0.9, 3.3, 5.0, 0,-4, 2.7, 0.55, 0.26)
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(0.7, 0.9, 3.3, 5.0, 0, 4,-2.7, 0.55, 0.26)
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(0.7, 0.9, 3.3, 5.0, 0, 4, 2.7,-0.55, 0.26)
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(0.7, 0.9, 3.3, 5.0, 0, 4, 2.7, 0.55,-0.26)
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(ones(8))
        @test_throws ArgumentError JS_BWG_HNE_DL{1,40}(ones(10))
        @test_throws ErrorException JS_BWG_HNE_DL(ones(9))
        @test_throws ErrorException JS_BWG_HNE_DL(0.7, 0.9, 3.3, 5.0, 0, 4, 2.7, 0.55, 0.26)
    end
end


text:
"""
    Uniform(a,b)

The *continuous uniform distribution* over an interval ``[a, b]`` has probability density function

```math
f(x; a, b) = \\frac{1}{b - a}, \\quad a \\le x \\le b
```

```julia
Uniform()        # Uniform distribution over [0, 1]
Uniform(a, b)    # Uniform distribution over [a, b]

params(d)        # Get the parameters, i.e. (a, b)
minimum(d)       # Get the lower bound, i.e. a
maximum(d)       # Get the upper bound, i.e. b
location(d)      # Get the location parameter, i.e. a
scale(d)         # Get the scale parameter, i.e. b - a
```

External links

* [Uniform distribution (continuous) on Wikipedia](http://en.wikipedia.org/wiki/Uniform_distribution_(continuous))

"""
struct Uniform{T<:Real} <: ContinuousUnivariateDistribution
    a::T
    b::T
    Uniform{T}(a::T, b::T) where {T <: Real} = new{T}(a, b)
end

function Uniform(a::T, b::T; check_args=true) where {T <: Real}
    check_args && @check_args(Uniform, a < b)
    return Uniform{T}(a, b)
end

Uniform(a::Real, b::Real) = Uniform(promote(a, b)...)
Uniform(a::Integer, b::Integer) = Uniform(float(a), float(b))
Uniform() = Uniform(0.0, 1.0, check_args=false)

function Uniform(::Type{T}, a, b) where {T <: Real}
    return Uniform(T(a), T(b))
end

@distr_support Uniform d.a d.b

#### Conversions
convert(::Type{Uniform{T}}, a::Real, b::Real) where {T<:Real} = Uniform(T(a), T(b))
convert(::Type{Uniform{T}}, d::Uniform{S}) where {T<:Real, S<:Real} = Uniform(T(d.a), T(d.b), check_args=false)

#### Parameters

params(d::Uniform) = (d.a, d.b)
partype(::Uniform{T}) where {T<:Real} = T

location(d::Uniform) = d.a
scale(d::Uniform) = d.b - d.a

#### Statistics

mean(d::Uniform) = middle(d.a, d.b)
median(d::Uniform) = mean(d)
mode(d::Uniform) = mean(d)
modes(d::Uniform) = Float64[]

var(d::Uniform) = (w = d.b - d.a; w^2 / 12)

skewness(d::Uniform{T}) where {T<:Real} = zero(T)
kurtosis(d::Uniform{T}) where {T<:Real} = -6/5*one(T)

entropy(d::Uniform) = log(d.b - d.a)

#### Evaluation

pdf(d::Uniform{T}, x::Real) where {T<:Real} = insupport(d, x) ? 1 / (d.b - d.a) : zero(T)
logpdf(d::Uniform{T}, x::Real) where {T<:Real} = insupport(d, x) ? -log(d.b - d.a) : -T(Inf)

function cdf(d::Uniform{T}, x::Real) where T<:Real
    (a, b) = params(d)
    x <= a ? zero(T) :
    x >= d.b ? one(T) : (x - a) / (b - a)
end

function ccdf(d::Uniform{T}, x::Real) where T<:Real
    (a, b) = params(d)
    x <= a ? one(T) :
    x >= d.b ? zero(T) : (b - x) / (b - a)
end

quantile(d::Uniform, p::Real) = d.a + p * (d.b - d.a)
cquantile(d::Uniform, p::Real) = d.b + p * (d.a - d.b)

function mgf(d::Uniform, t::Real)
    (a, b) = params(d)
    u = (b - a) * t / 2
    u == zero(u) && return one(u)
    v = (a + b) * t / 2
    exp(v) * (sinh(u) / u)
end

function cf(d::Uniform, t::Real)
    (a, b) = params(d)
    u = (b - a) * t / 2
    u == zero(u) && return complex(one(u))
    v = (a + b) * t / 2
    cis(v) * (sin(u) / u)
end

#### Sampling

rand(rng::AbstractRNG, d::Uniform) = d.a + (d.b - d.a) * rand(rng)

#### Fitting

function fit_mle(::Type{<:Uniform}, x::AbstractArray{T}) where T<:Real
    if isempty(x)
        throw(ArgumentError("x cannot be empty."))
    end

    xmin = xmax = x[1]
    for i = 2:length(x)
        xi = x[i]
        if xi < xmin
            xmin = xi
        elseif xi > xmax
            xmax = xi
        end
    end

    Uniform(xmin, xmax)
end


text:
function getUpdatedFactoredVal_2D(HO::Bool,kappa_squared::Array{Float64,2},T::Array{EikTtype,2},Done::Array{Bool,2},loc1::Int64,
									loc2::Int64,h::Array{Float64,1},hinv::Array{Float64,1},src::Array{Int64,1},
									T0loc::Float64, G0loc::Array{Float64,1}, OpLoc::Array{Int8,1},A::Array{Float64,1},B::Array{Float64,1})
# op: -1 for backward. 1 for forward. -2/2 for 2nd order backward/forward.
# A and B are just containers for answers so we won't allocate tuples all the time....
if HO
	#answers are in A,B,OpLoc
	(t1,t1a) = calcDirectionHO_2D(1, kappa_squared, T, Done, loc1, loc2, h, hinv, src, T0loc, G0loc, OpLoc, A, B);
	(t2,t2a) = calcDirectionHO_2D(2, kappa_squared, T, Done, loc1, loc2, h, hinv, src, T0loc, G0loc, OpLoc, A, B);
else
	#answers are in A,B,OpLoc
	t1 = calcDirectionFO_2D(1, kappa_squared, T, Done, loc1, loc2, h, hinv, src, T0loc, G0loc, OpLoc, A, B);
	t2 = calcDirectionFO_2D(2, kappa_squared, T, Done, loc1, loc2, h, hinv, src, T0loc, G0loc, OpLoc, A, B);
end

#### Quadratic Solve
A1 = A[1]; A2 = A[2]; B1 = B[1]; B2 = B[2];
a = A1*A1 + A2*A2; b = -A1*B1-A2*B2; c = B1*B1 + B2*B2; # b is divided by 2 here for easing the quadratic solve.
T_loc = solvePiecewiseQuadratic(A1,B1,A2,B2,kappa_squared[loc1,loc2],a,b,c,OpLoc);

if FactoredEikonalFastMarching.imposeMonotonicity
	if (t1 > 0.0 && T_loc*T0loc < t1+1e-16)
		if OpLoc[1]==-1 || OpLoc[1]==1
			A1 = T0loc/h[1];
			B1 = t1/h[1];
		else
			A1 = (3.0*T0loc)/(2.0*h[1]);
			B1 = (4.0*t1 - t1a)/(2.0*h[1]);
		end
		a = A1*A1 + A2*A2; b = -A1*B1-A2*B2; c = B1*B1 + B2*B2; # b is divided by 2 here for easing the quadratic solve.
		T_loc = solvePiecewiseQuadratic(A1,B1,A2,B2,kappa_squared[loc1,loc2],a,b,c,OpLoc);
	elseif (t2 > 0.0 && T_loc*T0loc < t2+1e-16)
		if OpLoc[2]==-1 || OpLoc[2]==1
			A2 = T0loc/h[2];
			B2 = t2/h[2];
		else
			A2 = (3.0*T0loc)/(2.0*h[2]);
			B2 = (4.0*t2 - t2a)/(2.0*h[2]);
		end
		a = A1*A1 + A2*A2; b = -A1*B1-A2*B2; c = B1*B1 + B2*B2; # b is divided by 2 here for easing the quadratic solve.
		T_loc = solvePiecewiseQuadratic(A1,B1,A2,B2,kappa_squared[loc1,loc2],a,b,c,OpLoc);
	end
end
return T_loc;
end

function solveQuadratic(a::Float64,b::Float64,c::Float64,fsq::Float64)
# Solution of a quadratic equation based on:
# t = (-b/2 + sqrt(b^2/4 - ac))/a.
# b in the arguments is actually b/2 of the real equation.

c -= fsq;
in_sqrt = b*b - a*c;
if (in_sqrt > 0.0)
    T_loc = (-b + sqrt(in_sqrt))/(a);
else
    T_loc = 0.0;
end
return T_loc;
end

function solvePiecewiseQuadratic(A1::Float64,B1::Float64,A2::Float64,B2::Float64,fsq::Float64,
							a::Float64,b::Float64,c::Float64,OpLoc::Array{Int8,1})
T_loc = solveQuadratic(a,b,c,fsq);
g1 = (A1*T_loc - B1);
g2 = (A2*T_loc - B2);
if T_loc == 0.0 || g1 < 0.0 || g2 < 0.0
	val1 = (OpLoc[1]==0) ? Inf : B1/A1;
	val2 = (OpLoc[2]==0) ? Inf : B2/A2;
	if val1 < val2
		f = sqrt(fsq);
		T_loc = (f + B1) / A1;
		OpLoc[2] = 0;
	else
		f = sqrt(fsq);
		T_loc = (f + B2) / A2;
		OpLoc[1] = 0;
	end
end
return T_loc
end

function calcDirectionHO_2D(dim::Int64,kappa_squared::Array{Float64,2},T::Array{EikTtype,2},Done::Array{Bool,2},
							loc1::Int64,loc2::Int64,h::Array{Float64,1},hinv::Array{Float64,1},src::Array{Int64,1},
							T0loc::Float64,G0loc::Array{Float64,1},OpLoc::Array{Int8,1},A::Array{Float64,1},B::Array{Float64,1})
if dim==1
	loc1p1 = loc1 + 1;
	loc1m1 = loc1 - 1;
	loc1p2 = loc1 + 2;
	loc1m2 = loc1 - 2;
	loc2p1 = loc2m1 = loc2p2 = loc2m2 = loc2;
else # dim is assumed to be 2
	loc2p1 = loc2 + 1;
	loc2m1 = loc2 - 1;
	loc2p2 = loc2 + 2;
	loc2m2 = loc2 - 2;
	loc1p1 = loc1m1 = loc1p2 = loc1m2 = loc1;
end

tBWD = 0.0;
tFWD = 0.0;

ChooseBWD = getPaddedArr2D(Done,loc1m1,loc2m1);
if ChooseBWD
	tBWD = T[loc1m1,loc2m1]*T02D(h,src,loc1m1,loc2m1);
end
ChooseFWD = getPaddedArr2D(Done,loc1p1,loc2p1);
if ChooseFWD
	tFWD = T[loc1p1,loc2p1]*T02D(h,src,loc1p1,loc2p1)
end
if ChooseBWD && ChooseFWD
	ChooseFWD = tFWD < tBWD;
	ChooseBWD = !ChooseFWD;
end

A[dim] = B[dim] = 0.0;
OpLoc[dim] = 0;
t = T0loc*hinv[dim];
if ChooseBWD
	if getPaddedArr2D(Done,loc1m2,loc2m2) && tBWD > T[loc1m2,loc2m2]*T02D(h,src,loc1m2,loc2m2)
		@inbounds A[dim] = 1.5*t + G0loc[dim]; #going for second order!!!
        @inbounds B[dim] = (2.0*T[loc1m1,loc2m1] - 0.5*T[loc1m2,loc2m2])*t;
        @inbounds OpLoc[dim] = -2;
		return tBWD,T[loc1m2,loc2m2]*T02D(h,src,loc1m2,loc2m2);
	else # first order.
		@inbounds A[dim] = t + G0loc[dim];
		@inbounds B[dim] = T[loc1m1,loc2m1]*t;
		@inbounds OpLoc[dim] = -1; # Choosing N means backward derivative.
		return tBWD,0.0;
	end

elseif ChooseFWD
	@inbounds if getPaddedArr2D(Done,loc1p2,loc2p2) && tFWD > T[loc1p2,loc2p2]*T02D(h,src,loc1p2,loc2p2)
		@inbounds A[dim] = 1.5*t - G0loc[dim];
        @inbounds B[dim] = (2.0*T[loc1p1,loc2p1] - 0.5*T[loc1p2,loc2p2])*t;
        @inbounds OpLoc[dim] = 2;
		return tFWD,T[loc1p2,loc2p2]*T02D(h,src,loc1p2,loc2p2);
	else
		@inbounds A[dim] = t - G0loc[dim];
		@inbounds B[dim] = T[loc1p1,loc2p1]*t;
		@inbounds OpLoc[dim] = 1;
		return tFWD,0.0;
	end

end
return 0.0,0.0;
end

function calcDirectionFO_2D(dim::Int64,kappa_squared::Array{Float64,2},T::Array{EikTtype,2},Done::Array{Bool,2},loc1::Int64,loc2::Int64,
							h::Array{Float64,1},hinv::Array{Float64,1},src::Array{Int64,1},T0loc::Float64,G0loc::Array{Float64,1},
							OpLoc::Array{Int8,1},A::Array{Float64,1},B::Array{Float64,1})

if dim==1
	loc1p1 = loc1 + 1;
	loc1m1 = loc1 - 1;
	loc2p1 = loc2m1 = loc2;
else # dim is assumed to be 2
	loc2p1 = loc2 + 1;
	loc2m1 = loc2 - 1;
	loc1p1 = loc1m1 = loc1;
end

tBWD = 0.0;
tFWD = 0.0;

ChooseBWD = getPaddedArr2D(Done,loc1m1,loc2m1);
ChooseFWD = getPaddedArr2D(Done,loc1p1,loc2p1);

if ChooseBWD && ChooseFWD
	tBWD = T[loc1m1,loc2m1]*T02D(h,src,loc1m1,loc2m1);
	tFWD = T[loc1p1,loc2p1]*T02D(h,src,loc1p1,loc2p1)
	@inbounds ChooseFWD = tFWD < tBWD;
	ChooseBWD = !ChooseFWD;
elseif FactoredEikonalFastMarching.imposeMonotonicity
	if ChooseBWD
		tBWD = T[loc1m1,loc2m1]*T02D(h,src,loc1m1,loc2m1);
	end
	if ChooseFWD
		tFWD = T[loc1p1,loc2p1]*T02D(h,src,loc1p1,loc2p1)
	end
end

@inbounds A[dim] = B[dim] = 0.0;
OpLoc[dim] = 0;
t = T0loc*hinv[dim];
if ChooseBWD
	@inbounds A[dim] = t + G0loc[dim];
	@inbounds B[dim] = T[loc1m1,loc2m1]*t;
	@inbounds OpLoc[dim] = -1; # Choosing N means backward derivative.
	return tBWD;
elseif ChooseFWD
	@inbounds A[dim] = t - G0loc[dim];
	@inbounds B[dim] = T[loc1p1,loc2p1]*t;
	@inbounds OpLoc[dim] = 1;
	return tFWD;
end
return 0.0;
end


text:
#!/usr/bin/julia

# Trizen
# 17 January 2017
# https://github.com/trizen

# Generates the Mandelbrot set.

# See also:
#   https://en.wikipedia.org/wiki/Mandelbrot_set
#   https://trizenx.blogspot.ro/2017/01/mandelbrot-set.html

using Images

@inline function hsv2rgb(h, s, v)
    c = v * s
    x = c * (1 - abs(((h/60) % 2) - 1))
    m = v - c

    if h < 60
        r,g,b = (c, x, 0)
    elseif h < 120
        r,g,b = (x, c, 0)
    elseif h < 180
        r,g,b = (0, c, x)
    elseif h < 240
        r,g,b = (0, x, c)
    elseif h < 300
        r,g,b = (x, 0, c)
    else
        r,g,b = (c, 0, x)
    end

    (r + m), (b + m), (g + m)
end

function mandelbrot()

    w, h = 1000, 1000

    zoom  = 0.5
    moveX = 0
    moveY = 0

    maxIter = 100
    img = zeros(RGB{Float64}, h, w)

    for x in 1:w, y in 1:h
        i = maxIter
        c = Complex(
            (2*x - w) / (w * zoom) + moveX,
            (2*y - h) / (h * zoom) + moveY
        )
        z = c
        while abs(z) < 2 && (i -= 1) > 0
            z = z^2 + c
        end
        r,g,b = hsv2rgb(i / maxIter * 360, 1, i / maxIter)
        img[y,x] = RGB{Float64}(r, g, b)
    end

    println("Generating image...")
    save("mandelbrot_set.png", img)
end

mandelbrot()

max_stars_repo_name: trizen/julia-scripts

max_issues_repo_name: trizen/julia-scripts

max_forks_repo_name: trizen/julia-scripts


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

using Markdown
using InteractiveUtils

# ╔═╡ a7288f0e-92c2-11eb-1f09-55b1249cddfc
using ShortCodes

# ╔═╡ b4638c6e-92c2-11eb-3455-297ca53dbf37
md" # ShortCodes

Simple embedding for [Pluto notebooks](https://github.com/fonsp/Pluto.jl)
"

# ╔═╡ bf967628-92c2-11eb-0794-654da6ac5292
md"# Twitter"

# ╔═╡ c4650640-92c2-11eb-2a5b-ed1dc13273ac
Twitter(1314967811626872842)

# ╔═╡ c90a21b6-92c2-11eb-0020-cf0095378602
md"# YouTube
Embed a video and seek to the given point in the video."

# ╔═╡ d5e1705e-92c2-11eb-2369-cba030f80467
YouTube("IAF8DjrQSSk",18,27)

# ╔═╡ db03ba94-92c2-11eb-0d9e-9382dc14f783
md"# Flickr"

# ╔═╡ e02ef00c-92c2-11eb-0036-e9f6a7a34ddc
Flickr(29110717138)

# ╔═╡ e7c836f4-92c2-11eb-3f84-77ffa870187e
md"# Embed Web Page"

# ╔═╡ e9db6308-92c2-11eb-0dda-09b6a1e6bb7e
WebPage("https://julialang.org/downloads/#current_stable_release")

# ╔═╡ f2f0fdd6-92c2-11eb-2e52-c5ea0f9288fc
md"# Vimeo"

# ╔═╡ feb4b4e6-92c2-11eb-0fe8-895a5ee0b084
Vimeo(171764413)

# ╔═╡ 96e66150-c4bb-4c77-b752-d04f8d366bca
md"# DOI
DOI information via [opencitations.net](https://opencitations.net) and [doi.org](https://doi.org)"

# ╔═╡ 8079cb71-95d7-4849-b5a4-abbb43f038f8
DOI("10.1137/141000671")

# ╔═╡ 1cda6524-92c3-11eb-145d-333251ab7498
md"# GraphViz"

# ╔═╡ 23e1b908-92c3-11eb-07c7-79c227f37cd8
GraphViz("digraph G {Hello->World}")

# ╔═╡ f001ad0c-92c3-11eb-15dd-0b6029eba08c
md"# Mermaid"

# ╔═╡ faa2b3f2-92c3-11eb-36a2-b716c6113df4
Mermaid("gantt
section Section
Completed :done,    des1, 2014-01-06,2014-01-08
Active        :active,  des2, 2014-01-07, 3d
Parallel 1   :         des3, after des1, 1d
Parallel 2   :         des4, after des1, 1d
Parallel 3   :         des5, after des3, 1d
Parallel 4   :         des6, after des4, 1d")

# ╔═╡ 05880a9e-92c4-11eb-1ca6-25556245f92d
md"# BlockDiag"

# ╔═╡ 0c92c8ea-92c4-11eb-08cd-f9e7d4cbdf24
BlockDiag("""blockdiag {
  Kroki -> generates -> "Block diagrams";
  Kroki -> is -> "very easy!";

  Kroki [color = "greenyellow"];
  "Block diagrams" [color = "pink"];
  "very easy!" [color = "orange"];
}""")

# ╔═╡ d4dd1922-92c4-11eb-3dff-a71dd1f96782
md"# PlantUML"

# ╔═╡ dcbec424-92c4-11eb-2ce6-d3ac255b3099
PlantUML("@startmindmap
skinparam monochrome true
+ OS
++ Ubuntu
+++ Linux Mint
+++ Kubuntu
+++ Lubuntu
+++ KDE Neon
++ LMDE
++ SolydXK
++ SteamOS
++ Raspbian
-- Windows 95
-- Windows 98
-- Windows NT
--- Windows 8
--- Windows 10
@endmindmap")

# ╔═╡ 00000000-0000-0000-0000-000000000001
PLUTO_PROJECT_TOML_CONTENTS = """
[deps]
ShortCodes = "f62ebe17-55c5-4640-972f-b59c0dd11ccf"

[compat]
ShortCodes = "~0.3.2"
"""

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

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

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

[[CodecZlib]]
deps = ["TranscodingStreams", "Zlib_jll"]
git-tree-sha1 = "ded953804d019afa9a3f98981d99b33e3db7b6da"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.0"

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

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

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

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

[[JSON3]]
deps = ["Dates", "Mmap", "Parsers", "StructTypes", "UUIDs"]
git-tree-sha1 = "b3e5984da3c6c95bcf6931760387ff2e64f508f3"
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
version = "1.9.1"

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

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

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

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

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

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

[[Memoize]]
deps = ["MacroTools"]
git-tree-sha1 = "2b1dfcba103de714d31c033b5dacc2e4a12c7caa"
uuid = "c03570c3-d221-55d1-a50c-7939bbd78826"
version = "0.4.4"

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

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

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

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

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

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

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

[[ShortCodes]]
deps = ["Base64", "CodecZlib", "HTTP", "JSON3", "Memoize", "UUIDs"]
git-tree-sha1 = "866962b3cc79ad3fee73f67408c649498bad1ac0"
uuid = "f62ebe17-55c5-4640-972f-b59c0dd11ccf"
version = "0.3.2"

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

[[StructTypes]]
deps = ["Dates", "UUIDs"]
git-tree-sha1 = "8445bf99a36d703a09c601f9a57e2f83000ef2ae"
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
version = "1.7.3"

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

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

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

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

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

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

# ╔═╡ Cell order:
# ╠═a7288f0e-92c2-11eb-1f09-55b1249cddfc
# ╟─b4638c6e-92c2-11eb-3455-297ca53dbf37
# ╟─bf967628-92c2-11eb-0794-654da6ac5292
# ╠═c4650640-92c2-11eb-2a5b-ed1dc13273ac
# ╠═c90a21b6-92c2-11eb-0020-cf0095378602
# ╠═d5e1705e-92c2-11eb-2369-cba030f80467
# ╟─db03ba94-92c2-11eb-0d9e-9382dc14f783
# ╠═e02ef00c-92c2-11eb-0036-e9f6a7a34ddc
# ╟─e7c836f4-92c2-11eb-3f84-77ffa870187e
# ╠═e9db6308-92c2-11eb-0dda-09b6a1e6bb7e
# ╟─f2f0fdd6-92c2-11eb-2e52-c5ea0f9288fc
# ╠═feb4b4e6-92c2-11eb-0fe8-895a5ee0b084
# ╟─96e66150-c4bb-4c77-b752-d04f8d366bca
# ╠═8079cb71-95d7-4849-b5a4-abbb43f038f8
# ╟─1cda6524-92c3-11eb-145d-333251ab7498
# ╠═23e1b908-92c3-11eb-07c7-79c227f37cd8
# ╟─f001ad0c-92c3-11eb-15dd-0b6029eba08c
# ╠═faa2b3f2-92c3-11eb-36a2-b716c6113df4
# ╟─05880a9e-92c4-11eb-1ca6-25556245f92d
# ╠═0c92c8ea-92c4-11eb-08cd-f9e7d4cbdf24
# ╟─d4dd1922-92c4-11eb-3dff-a71dd1f96782
# ╠═dcbec424-92c4-11eb-2ce6-d3ac255b3099
# ╟─00000000-0000-0000-0000-000000000001
# ╟─00000000-0000-0000-0000-000000000002


text:
using DrakeLCMTypes
using Test
using LCMCore
using LCMCore: fingerprint

#=
The following Python code was used to retrieve all of the
fingerprints for the various drake lcmtypes automatically:

import sys
import inspect
import struct
import drake

for name, obj in inspect.getmembers(drake):
    if inspect.isclass(obj):
        print("{:s} => {:d},".format(name, struct.unpack('q', obj._get_packed_fingerprint())[0]))

=#

"""
Equality test for most types, but we compare LCMType instances
by looking at their fields, since otherwise == just falls back
to === which compares object identity and is thus not very
informative.
"""
closeenough(x, y) = x == y
function closeenough(x::LCMType, y::LCMType)
    (typeof(x) == typeof(y)) || return false
    for name in fieldnames(typeof(x))
        closeenough(getfield(x, name), getfield(y, name)) || return false
    end
    true
end

@testset "fingerprints" begin
    expected_fingerprints_network_order = Dict(
        body_motion_data_t => -1697438386000409426,
        body_wrench_data_t => 4386893263873254047,
        drake_signal_t => 7238120976706690118,
        driving_control_cmd_t => -6896084824078521841,
        foot_flag_t => -8864446532455026203,
        force_torque_t => -4222868804320616333,
        joint_pd_override_t => 5714105219971151977,
        piecewise_polynomial_t => -8838642192454639028,
        polynomial_t => 5357274285886765929,
        polynomial_matrix_t => -1258712767803654590,
        qp_controller_input_t => -3544374615258239713,
        quadrotor_input_t => 8036605081750588725,
        quadrotor_output_t => 2366092281809915326,
        robot_state_t => 8839665116654389949,
        scope_data_t => 6915476259009230748,
        simulation_command_t => 9013348952217922704,
        support_data_t => 6151770265999148129,
        whole_body_data_t => -2520944405135015033,
        zmp_com_observer_state_t => -35953723948848452,
        zmp_data_t => 7529117173982992449,
    )

    for (lcmtype, fingerprint_network_order) in expected_fingerprints_network_order
        @testset "$lcmtype" begin
            @testset "constructor" begin
                msg = lcmtype()
                for name in fieldnames(typeof(msg))
                    @test closeenough(getfield(msg, name), LCMCore.defaultval(typeof(getfield(msg, name))))
                end
            end
            @testset "fingerprint" begin
                @test hton(fingerprint(lcmtype)) == fingerprint_network_order
            end
        end
    end
end


text:
using NullableArrays
using DataArrays
using StatsBase

srand(1)
N = 5_000_000

function profile_stats_methods()
    A = rand(N)
    B = rand(Bool, N)
    X = NullableArray(A)
    Y = NullableArray(A, B)
    D = DataArray(A)
    E = DataArray(A, B)

    profile_mean(A, X, D, Y, E)
    profile_var(A, X, D, Y, E)
    nothing
end

function profile_mean(A, X, D, Y, E)
    W = WeightVec(rand(N))

    mean(A)
    println("Method: mean(A) (0 missing entries)")
    print("  for Array{Float64}:          ")
    @time(mean(A))
    mean(X)
    print("  for NullableArray{Float64}:  ")
    @time(mean(X))
    mean(D)
    print("  for DataArray{Float64}:      ")
    @time(mean(D))
    println()

    mean(Y, skipnull=false)
    println("Method: mean(A) (~half missing entries, skip=false)")
    print("  for NullableArray{Float64}:  ")
    @time(mean(Y, skipnull=false))
    mean(E, skipna=false)
    print("  for DataArray{Float64}:      ")
    @time(mean(E, skipna=false))
    println()

    mean(Y, skipnull=true)
    println("Method: mean(A) (~half missing entries, skip=true)")
    print("  for NullableArray{Float64}:  ")
    @time(mean(Y, skipnull=true))
    mean(E, skipna=true)
    print("  for DataArray{Float64}:      ")
    @time(mean(E, skipna=true))
    println()

    mean(A, W)
    println("Method: mean(A, w::WeightVec{W, V}) (0 missing entries, V<:Array)")
    print("  for Array{Float64}:          ")
    @time(mean(A, W))
    mean(X, W)
    print("  for NullableArray{Float64}:  ")
    @time(mean(X, W))
    mean(D, W)
    print("  for DataArray{Float64}:      ")
    @time(mean(D, W))
    println()

    println("Method: mean(A, W::WeightVec) (~half missing entries, skip=false)")
    mean(Y, W, skipnull=false)
    print("  for NullableArray{Float64}:  ")
    @time(mean(Y, W, skipnull=false))
    mean(E, W, skipna=false)
    print("  for DataArray{Float64}:      ")
    @time(mean(E, W, skipna=false))
    println()

    println("Method: mean(A, W::WeightVec) (~half missing entries, skip=true)")
    mean(Y, W, skipnull=true)
    print("  for NullableArray{Float64}:  ")
    @time(mean(Y,  W, skipnull=true))
    mean(E, W, skipna=true)
    print("  for DataArray{Float64}:      ")
    @time(mean(E, W, skipna=true))
    println()
end

function profile_var(A, X, D, Y, E)
    mu = mean(A)
    mu2 = mean(X, skipnull=true)

    varm(A, mu)
    println("Method: varm(A, mu) (0 missing entries)")
    print("  for Array{Float64}:          ")
    @time(varm(A, mu))
    println("                                  ", varm(A, mu))
    varm(X, mu)
    print("  for NullableArray{Float64}:  ")
    @time(varm(X, mu))
    varm(D, mu)
    print("  for DataArray{Float64}:      ")
    @time(varm(D, mu))
    println()

    varm(Y, mu; skipnull=false)
    println("Method: varm(A, mu) (~half missing entries, skip=false)")
    print("  for NullableArray{Float64}:  ")
    @time(varm(Y, mu; skipnull=false))
    varm(E, mu; skipna=false)
    print("  for DataArray{Float64}:      ")
    @time(varm(E, mu; skipna=false))
    println()

    varm(Y, mu; skipnull=true)
    println("Method: varm(A, mu) (~half missing entries, skip=true)")
    print("  for NullableArray{Float64}:  ")
    @time(varm(Y, mu; skipnull=true))
    varm(E, mu; skipna=true)
    print("  for DataArray{Float64}:      ")
    @time(varm(E, mu; skipna=true))
    println()
end

max_stars_repo_name: davidagold/NullableStats

max_issues_repo_name: davidagold/NullableStats

max_forks_repo_name: davidagold/NullableStats


text:
module MyExample

include("extra_file.jl")
export my_f

end


text:
@doc """
A RollCallEncoding object represents the conventions used to represent a
roll-call data set in terms of a matrix of integers. The encoding specifies
which integers are treated as 'yea' votes, which integers are treated as 'nay'
votes, which integers are treated as 'missing from vote' votes; and which
integers are treated as 'inactive in legislative body' votes.
""" ->
immutable RollCallEncoding{T1 <: Tuple, T2 <: Tuple, T3 <: Tuple, T4 <: Tuple}
    yea::T1
    nay::T2
    missing::T3
    inactive::T4
end

@doc """
Construct a RollCallEncoding object using the defaults appropriate for the
data found on VoteView.com.
""" ->
function RollCallEncoding(
    yea = (1, 2, 3),
    nay = (4, 5, 6),
    missing = (7, 8, 9),
    inactive = (0,),
)
    RollCallEncoding(yea, nay, missing, inactive)
end

max_stars_repo_name: johnmyleswhite/RollCallDataIO

max_issues_repo_name: johnmyleswhite/RollCallDataIO

max_forks_repo_name: johnmyleswhite/RollCallDataIO