text:
module ReadDatastores

export
    ReadDatastore,
    PairedReads,
    PairedReadOrientation,
    FwRv,
    RvFw,
    LongReads,
    LinkedReads,
    UCDavis10x,
    DatastoreBuffer,
    name,
    max_read_length,
    orientation,
    load_sequence!,
    buffer,
    read_tag,
    stream,
    @openreads,
    @reads_str

using BioSequences, FASTX

const ReadDatastoreMAGIC = 0x05D5

@enum Filetype::UInt16 begin
    PairedDS = 1
    LongDS = 2
    LinkedDS = 3
end

###
### Writing helpers
###

@inline function writestring(fd::IO, s::AbstractString)
    write(fd, s) + write(fd, '\0')
end

@inline function write_flat_vector(fd::IO, v::Vector{T}) where {T}
    n = UInt64(length(v))
    return write(fd, n) + write(fd, v)
end

@inline function read_flat_vector!(fd::IO, v::Vector{T}) where {T}
    n = read(fd, UInt64)
    v = resize!(n)
    unsafe_read(fd, pointer(v), n * sizeof(T))
    return v
end

@inline function read_flat_vector(fd::IO, ::Type{T}) where {T}
    n = read(fd, UInt64)
    v = Vector{T}(undef, n)
    unsafe_read(fd, pointer(v), n * sizeof(T))
    return v
end

###
### Abstract ReadDatastore type
###
abstract type ReadDatastore{S<:LongSequence} end

###
### ReadDatastore custom exceptions
###
struct MissingMagicError <: Exception
    filename::String
end

function Base.showerror(io::IO, e::MissingMagicError)
    print(io, "MissingMagicError: the file ")
    print(io, e.filename)
    print(io, " does not appear to be a valid read datastore file")
    print(io, ", it does not begin with the expected magic bytes.")
end

struct DatastoreTypeError{D<:ReadDatastore} <: Exception
    filename::String
    dstype::Filetype
end

function Base.showerror(io::IO, e::DatastoreTypeError{D}) where {D}
    print(io, "DatastoreTypeError: ")
    print(io, e.filename)
    print(io, " contains a ")
    if e.dstype === PairedDS
        print(io, "paired read datastore")
    elseif e.dstype === LongDS
        print(io, "long read datastore")
    elseif e.dstype === LinkedDS
        print(io, "linked read datastore")
    else
        print(io, "unknown datastore type")
    end
    print(io, " and cannot be opened as a ")
    print(io, D)
end

struct DatastoreVersionError{D<:ReadDatastore} <: Exception
    version::Int
end

struct DatastoreEncodingError{D<:ReadDatastore} <: Exception
    filename::String
    bpe::Int
end

function Base.showerror(io::IO, e::DatastoreEncodingError{D}) where {D}
    print(io, "DatastoreEncodingError: ")
    print(io, e.filename)
    print(io, " encodes reads using ")
    print(io, e.bpe)
    print(io, " bits per element and cannot be opened as a ")
    print(io, D)
end

function __validate_datastore_header(io::IOStream, dstype::Type{D}) where {D<:ReadDatastore}
    magic = read(io, UInt16)
    dstype = reinterpret(Filetype, read(io, UInt16))
    version = read(io, UInt16)

    if magic !== ReadDatastoreMAGIC
        throw(MissingMagicError(io.name))
    end

    if dstype !== __ds_type_code(D)
        throw(DatastoreTypeError{D}(io.name, dstype))
    end

    if version !== __ds_version_code(D)
        throw(DatastoreVersionError{D}(version))
    end

    bps = read(io, UInt64)

    if bps != BioSequences.bits_per_symbol(Alphabet(eltype(D)))
        throw(DatastoreEncodingError{D}(io.name, bps))
    end
end

###
### Concrete ReadDatastore type definitions
###
include("short-reads.jl")
include("paired-reads.jl")
include("long-reads.jl")
include("linked-reads.jl")
include("sequence-buffer.jl")

function Base.showerror(io::IO, e::DatastoreVersionError{<:PairedReads})
    print(io, "DatastoreVersionError: ")
    print(io, "file format version of paired read datastore file (v")
    print(io, Int(e.version))
    print(io, ") is deprecated: this version of ReadDatastores.jl supports v")
    print(io, Int(PairedDS_Version))
end

function Base.showerror(io::IO, e::DatastoreVersionError{<:LongReads})
    print(io, "DatastoreVersionError: ")
    print(io, "file format version of long read datastore file (v")
    print(io, Int(e.version))
    print(io, ") is deprecated: this version of ReadDatastores.jl supports v")
    print(io, Int(LongDS_Version))
end

function Base.showerror(io::IO, e::DatastoreVersionError{<:LinkedReads})
    print(io, "DatastoreVersionError: ")
    print(io, "file format version of linked read datastore file (v")
    print(io, Int(e.version))
    print(io, ") is deprecated: this version of ReadDatastores.jl supports v")
    print(io, Int(LinkedDS_Version))
end

###
### ReadDatastore generics
###
@inline buffer(ds::ReadDatastore, buffer_size = DEFAULT_BUF_SIZE) = DatastoreBuffer(ds, buffer_size)

# TODO: Phase out
#"Get the length of the longest sequence in the datastore"
#@inline maxseqlen(ds::ReadDatastore) = ds.max_read_len

"Get the name of the datastore"
@inline name(ds::ReadDatastore) = ds.name

"Get a reference to the underlying filestream the datastore is using"
@inline stream(ds::ReadDatastore) = ds.stream

@inline Base.firstindex(ds::ReadDatastore) = 1
@inline Base.lastindex(ds::ReadDatastore) = length(ds)
@inline Base.eachindex(ds::ReadDatastore) = Base.OneTo(lastindex(ds))
@inline Base.IteratorSize(ds::ReadDatastore) = Base.HasLength()
@inline Base.IteratorEltype(ds::ReadDatastore) = Base.HasEltype()
@inline Base.eltype(::Type{<:ReadDatastore{T}}) where {T} = T
@inline Base.close(ds::ReadDatastore) = close(stream(ds))

@inline function Base.checkbounds(ds::ReadDatastore, i::Integer)
    if firstindex(ds) ≤ i ≤ lastindex(ds)
        return true
    end
    throw(BoundsError(ds, i))
end

@inline function Base.iterate(ds::ReadDatastore, state = 1)
    @inbounds if firstindex(ds) ≤ state ≤ lastindex(ds)
        return ds[state], state + 1
    else
        return nothing
    end
end

function Base.open(f::Function, ::Type{T}, filepath::AbstractString) where {T<:ReadDatastore}
    ds = open(T, filepath)
    try
        f(ds)
    finally
        close(ds)
    end
end

"""
    _load_sequence_data!(prds::PairedReads, seq::LongSequence{DNAAlphabet{4}})

Reads the sequence data from the current position of a datastore's stream, into
a destination sequence `seq`.

This function knows how much data to read from the stream, based on the sequence's
data blob (i.e. `sizeof(BioSequences.encoded_data(seq))`).

!!! warning
    Uses `unsafe_read`, makes the following assumptions - does not check any of them.

    - The stream is at the correct position, such that an `unsafe_read` will
      read the entirety of the sequence before hitting the end of file.
      Hitting EOF should result in an error being thrown anyway so...
    - The destination sequence is currently the correct size and has been resized
      appropriately before this function has been called.
    - The data in the stream of the datastore is encoded appropriately for the
      sequence type.
"""
function _load_sequence_data!(ds::ReadDatastore{T}, seq::T) where {T<:LongSequence}
    seqdata = BioSequences.encoded_data(seq)
    GC.@preserve seqdata unsafe_read(stream(ds), pointer(seqdata), sizeof(seqdata))
    return seq
end

function deduce_datastore_type(filename::String)::DataType
    open(filename, "r") do io
        seekstart(io)
        mn = read(io, UInt16)
        @assert mn === ReadDatastoreMAGIC
        tp = reinterpret(Filetype, read(io, UInt16))
        vn = read(io, UInt16)
        bpn = Int64(read(io, UInt64))
        if tp === PairedDS
            #@assert vn === PairedDS_Version
            if vn !== PairedDS_Version
                throw(DatastoreVersionError{PairedReads{DNAAlphabet{bpn}}}(vn))
            end
            out = PairedReads{DNAAlphabet{bpn}}
        elseif tp === LongDS
            @assert vn === LongDS_Version
            out = LongReads{DNAAlphabet{bpn}}
        elseif tp === LinkedDS
            @assert vn === LinkedDS_Version
            out = LinkedReads{DNAAlphabet{bpn}}
        else
            error("Unrecognized datastore type")
        end
        return out
    end
end

"""
    @openreads filename::String

A convenience macro for opening read datastores.

The open method for ReadDatastores requires the specific type of the ReadDatastore
as the first argument.

This can be cumbersome as the specific type of the datastore may be forgotten or
not known in the first place if the user recieved the datastore from a colleague.

This macro allows you to open a datastore using only the filename.

The macro opens the file, peeks at the header and deduces the type of datastore
contained in the file. It then returns a complete and correctly formed `open`
command for the datastore. This allows the user to forget about the specific
datastore type whilst still maintaining type certainty.
"""
macro openreads(filename::String)
    dstype = deduce_datastore_type(filename)
    return :(open($dstype, $filename))
end

"""
@openreads filename::String name

A convenience macro for opening read datastores and assigning it a name other
than the datastore's default name.

The open method for ReadDatastores requires the specific type of the ReadDatastore
as the first argument.

This can be cumbersome as the specific type of the datastore may be forgotten or
not known in the first place if the user recieved the datastore from a colleague.

This macro allows you to open a datastore using only the filename.

The macro opens the file, peeks at the header and deduces the type of datastore
contained in the file. It then returns a complete and correctly formed `open`
command for the datastore. This allows the user to forget about the specific
datastore type whilst still maintaining type certainty.
"""
macro openreads(filename::String, name::Symbol)
    dstype = deduce_datastore_type(filename)
    return :(open($dstype, $filename, $(QuoteNode(name))))
end

macro openreads(filename::String, binding::Symbol, expression::Expr)
    dstype = deduce_datastore_type(filename)
    quote
        open($dstype, $filename) do $(esc(binding))
            $(esc(expression))
        end
    end
end

macro openreads(filename::String, name::Symbol, binding::Symbol, expression::Expr)
    dstype = deduce_datastore_type(filename)
    quote
        open($dstype, $filename, $(QuoteNode(name))) do $(esc(binding))
            $(esc(expression))
        end
    end
end

macro openreads(filename::String, name::Symbol, fn::Symbol)
    dstype = deduce_datastore_type(filename)
    return :(open($fn, $dstype, $filename, $(QuoteNode(name))))
end

macro reads_str(filename::String)
    dstype = deduce_datastore_type(filename)
    return open(dstype, filename)
end

macro reads_str(filename::String, flag)
    dstype = deduce_datastore_type(filename)
    if flag === "s"
        return open(dstype, filename)
    elseif flag === "d"
        return :(open($dstype, $filename))
    else
        error("Invalid flag option")
    end
end

end # module


text:
# ---
# title: 784. Letter Case Permutation
# id: problem784
# author: Indigo
# date: 2021-01-28
# difficulty: Medium
# categories: Backtracking, Bit Manipulation
# link: <https://leetcode.com/problems/letter-case-permutation/description/>
# hidden: true
# ---
#
# Given a string S, we can transform every letter individually to be lowercase
# or uppercase to create another string.
#
# Return _a list of all possible strings we could create_. You can return the
# output in **any order**.
#
#
#
# **Example 1:**
#
#
#
#     Input: S = "a1b2"
#     Output: ["a1b2","a1B2","A1b2","A1B2"]
#
#
# **Example 2:**
#
#
#
#     Input: S = "3z4"
#     Output: ["3z4","3Z4"]
#
#
# **Example 3:**
#
#
#
#     Input: S = "12345"
#     Output: ["12345"]
#
#
# **Example 4:**
#
#
#
#     Input: S = "0"
#     Output: ["0"]
#
#
#
#
# **Constraints:**
#
#   * `S` will be a string with length between `1` and `12`.
#   * `S` will consist only of letters or digits.
#
#
## @lc code=start
using LeetCode

function letter_case_permutation(s::String)
    ans = [""]
    for i in s
        if isletter(i)
            tmp = ans[:]
            ans .*= lowercase(i)
            tmp .*= uppercase(i)
            append!(ans, tmp)
        else
            ans .*= i
        end
    end
    ans
end
## @lc code=end

ext: jl


text:
function lockPrediction(this::PredictionCenter)
	meanAbsError = {};
	meanRelError = {};
	errorHeader = {};
	extra = {};
	if this.testMode == 1 #PredictionCenter.TEST_MODE_DATASET
		if this.lockType == "waitTime"
			my_train_lock = this.trainConfig.lockWaitTime;
			my_test_lock = this.testConfig.lockWaitTime;
		elseif this.lockType == "numberOfLocks"
			my_train_lock = this.trainConfig.currentLockWait;
			my_test_lock = this.testConfig.currentLockWait;
		elseif this.lockType == "numberOfConflicts"
			my_train_lock = this.trainConfig.lockWaitTime;
			my_test_lock = this.testConfig.lockWaitTime;
		else
			error(string("Invalid lockType:", this.lockType));
		end

		if this.learnLock == true # re-learn it!
			#%taskDesc.emIters is hard-coded as 5 for now.
			domain_cost = barzanCurveFit(this.lockType, this.trainConfig.transactionCount, my_train_lock, [0.1 0.0000000001], [1000000 10], [50 0.01], [5 5]);
			lock_conf = [0.125 0.0001 domain_cost];
		elseif !isempty(this.lockConf)
			lock_conf = this.lockConf;
		else
			error("You should either let us re-learn or should give us the lock_conf to use!");
		end

		# %allPreds = useLockModel(lock_conf, this.testConfig.transactionCount, this.workloadName);
		allPreds = useLockModel(lock_conf, this.testConfig.transactionCount, "TPCC");

		if this.lockType == "waitTime"
			myPredictedLock = sum(allPreds.TimeSpentWaiting, 2);
			if(length(myPredictedLock)==1)
				myPredictedLock=myPredictedLock[1]
			end
		elseif this.lockType == "numberOfLocks"
			myPredictedLock = sum(allPreds.LocksBeingHeld, 2);
			if(length(myPredictedLock)==1)
				myPredictedLock=myPredictedLock[1]
			end
		elseif this.lockType == "numberOfConflicts"
			myPredictedLock = sum(allPreds.totalWaits, 2);
			if(length(myPredictedLock)==1)
				myPredictedLock=myPredictedLock[1]
			end
		else
                    error(string("Invalid lockType:", this.lockType));
		end

		classifierLinModel = barzanLinSolve(my_train_lock, this.trainConfig.transactionCount);
		classifierLinPredictions = barzanLinInvoke(classifierLinModel, this.testConfig.transactionCount);

		range = [1:1:size(this.trainConfig.transactionCount,2)];
		combs = collect(combinations(range,2))
		tempLen = length(combs)
		comb1 = zeros(tempLen,1);
		for i=tempLen:-1:1
			comb1[tempLen-i+1] = combs[i][1]
		end
		comb2 = zeros(tempLen,1);
		for i=tempLen:-1:1
			comb2[tempLen-i+1] = combs[i][2]
		end

		#Julia: may have some bugs
		blownTrainC = [this.trainConfig.transactionCount this.trainConfig.transactionCount.*this.trainConfig.transactionCount this.trainConfig.transactionCount[:, vec(comb1)].*this.trainConfig.transactionCount[:, vec(comb2)]];
		blownTestC = [this.testConfig.transactionCount this.testConfig.transactionCount.*this.testConfig.transactionCount this.testConfig.transactionCount[:, vec(comb1)].*this.testConfig.transactionCount[:, vec(comb2)]];
		classQuadModel = barzanLinSolve(my_train_lock, blownTrainC);
		classQuadPredictions = barzanLinInvoke(classQuadModel, blownTestC);

		treeModel = barzanRegressTreeLearn(my_train_lock, this.trainConfig.TPS);
		treePredictions = barzanRegressTreeInvoke(treeModel, this.testConfig.TPS);

		#% kccaModel = barzanKccaLearn(my_train_lock, blownTrainC);
		#% kccaPredictions = barzanKccaInvoke(kccaModel, blownTestC);

		#% allPreds = useLockModel([1 1 1 1], this.testConfig.transactionCount, this.workloadName);
		allPreds = useLockModel([1 1 1 1], this.testConfig.transactionCount, "TPCC");

		if this.lockType == "waitTime"
			thomasianPreds = sum(allPreds.TimeSpentWaiting, 2);
			if(length(thomasianPreds)==1)
				thomasianPreds=thomasianPreds[1]
			end
		elseif this.lockType == "numberOfLocks"
			thomasianPreds = sum(allPreds.LocksBeingHeld, 2);
			if(length(thomasianPreds)==1)
				thomasianPreds=thomasianPreds[1]
			end
		elseif this.lockType == "numberOfConflicts"
			thomasianPreds = sum(allPreds.totalWaits, 2);
			if(length(thomasianPreds)==1)
				thomasianPreds=thomasianPreds[1]
			end
		else
			error(string("Invalid lockType:", this.lockType));
		end

		temp = [my_test_lock myPredictedLock classifierLinPredictions classQuadPredictions treePredictions thomasianPreds];
		#% kccaPredictions omitted.

		#% by TPS only for now
		temp = [this.testConfig.TPS temp];

		temp = sortrows(temp);

		Xdata = {temp[:,1]};
		Ydata = {temp[:,2:end]};

		for i=3:7
			push!(meanAbsError, mae(temp[:,i], temp[:,2]));
			push!(meanRelError, mre(temp[:,i], temp[:,2]));
		end

		Xlabel = "TPS";
		Ylabel = "Total time spent acquiring row locks (seconds)";
		legends = {"Actual", "Our contention model", "LR+class", "quad+class", "Dec. tree regression", "Orig. Thomasian"};
		errorHeader = legends[2:6];
		title = "Lock Prediction";
	elseif this.testMode == 0 #PredictionCenter.TEST_MODE_MIXTURE_TPS

		testTPS = this.testSampleTPS;
		testTransactionCount = this.testSampleTransactionCount;

		if this.lockType == "waitTime"
			my_train_lock = this.trainConfig.lockWaitTime;
		elseif this.lockType == "numberOfLocks"
			my_train_lock = this.trainConfig.currentLockWait;
		elseif this.lockType == "numberOfConflicts"
			my_train_lock = this.trainConfig.lockWaitTime;
		else
			error(string("Invalid lockType:", this.lockType));
		end

		if this.learnLock == true # re-learn it!

			#% taskDesc.emIters is hard-coded as 5 for now.
			domain_cost = barzanCurveFit(this.lockType, this.trainConfig.transactionCount, my_train_lock, [0.1 0.0000000001], [1000000 10], [50 0.01], [5 5]);

			lock_conf = [0.125 0.0001 domain_cost];
		elseif !isempty(this.lockConf)
			lock_conf = this.lockConf;
		else
			error("You should either let us re-learn or should give us the lock_conf to use!");
		end
		#% allPreds = useLockModel(lock_conf, this.testConfig.transactionCount, this.workloadName);
		allPreds = useLockModel(lock_conf, testTransactionCount, "TPCC");
		if this.lockType == "waitTime"
			myPredictedLock = sum(allPreds.TimeSpentWaiting, 2);
			if(length(myPredictedLock)==1)
				myPredictedLock=myPredictedLock[1]
			end
		elseif this.lockType == "numberOfLocks"
			myPredictedLock = sum(allPreds.LocksBeingHeld, 2);
			if(length(myPredictedLock)==1)
				myPredictedLock=myPredictedLock[1]
			end
		elseif this.lockType == "numberOfConflicts"
			myPredictedLock = sum(allPreds.totalWaits, 2);
			if(length(myPredictedLock)==1)
				myPredictedLock=myPredictedLock[1]
			end
		else
                    error(string("Invalid lockType:", this.lockType));
		end

		classifierLinModel = barzanLinSolve(my_train_lock, this.trainConfig.transactionCount);
		classifierLinPredictions = barzanLinInvoke(classifierLinModel, testTransactionCount);

		range = [1:1:size(this.trainConfig.transactionCount,2)];
		combs = collect(combinations(range,2))
		tempLen = length(combs)
		comb1 = zeros(tempLen,1);
		for i=tempLen:-1:1
			comb1[tempLen-i+1] = combs[i][1]
		end
		comb2 = zeros(tempLen,1);
		for i=tempLen:-1:1
			comb2[tempLen-i+1] = combs[i][2]
		end

		blownTrainC = [this.trainConfig.transactionCount this.trainConfig.transactionCount.*this.trainConfig.transactionCount this.trainConfig.transactionCount[:, vec(comb1)].*this.trainConfig.transactionCount[:, vec(comb2)]];
		blownTestC = [testTransactionCount testTransactionCount.*testTransactionCount testTransactionCount[:, vec(comb1)].*testTransactionCount[:, vec(comb2)]];
		classQuadModel = barzanLinSolve(my_train_lock, blownTrainC);
		classQuadPredictions = barzanLinInvoke(classQuadModel, blownTestC);

		treeModel = barzanRegressTreeLearn(my_train_lock, this.trainConfig.TPS);
		treePredictions = barzanRegressTreeInvoke(treeModel, testTPS);

		#% kccaModel = barzanKccaLearn(my_train_lock, blownTrainC);
		#% kccaPredictions = barzanKccaInvoke(kccaModel, blownTestC);

		#% allPreds = useLockModel([1 1 1 1], this.testConfig.transactionCount, this.workloadName);
		allPreds = useLockModel([1 1 1 1], testTransactionCount, "TPCC");

		if this.lockType == "waitTime"
			thomasianPreds = sum(allPreds.TimeSpentWaiting, 2);
			if(length(thomasianPreds)==1)
				thomasianPreds=thomasianPreds[1]
			end
		elseif this.lockType == "numberOfLocks"
			thomasianPreds = sum(allPreds.LocksBeingHeld, 2);
			if(length(thomasianPreds)==1)
				thomasianPreds=thomasianPreds[1]
			end
		elseif this.lockType == "numberOfConflicts"
			thomasianPreds = sum(allPreds.totalWaits, 2);
			if(length(thomasianPreds)==1)
				thomasianPreds=thomasianPreds[1]
			end
		else
			error(string("Invalid lockType:", this.lockType));
		end

		temp = [myPredictedLock classifierLinPredictions classQuadPredictions treePredictions thomasianPreds];
		#% kccaPredictions omitted.

		#% by TPS only for now
		temp = [testTPS temp];

		temp = sortrows(temp);

		Xdata = {temp[:,1]};
		Ydata = {temp[:,2:end]};

		Xlabel = "TPS";
		Ylabel = "Total time spent acquiring row locks (seconds)";
		legends = {"Our contention model", "LR+class", "quad+class", "Dec. tree regression", "Orig. Thomasian"};
		title = "Lock Prediction";
            end
	title,legends,Xdata,Ydata,Xlabel,Ylabel,meanAbsError,meanRelError,errorHeader,extra
end # end function

max_stars_repo_name: barzan/dbseer

max_issues_repo_name: barzan/dbseer

max_forks_repo_name: barzan/dbseer


text:
module Dart
using SpecialFunctions
using LinearAlgebra

export mlsl

struct Sequential end
struct Threading end
struct SearchBox{T1, T2, T3, T4, T5}
    volume::T1
    lower::T2
    upper::T3
    bounds::T4
    widths::T5
end
function SearchBox(lower, upper)
    bounds = [(l, u) for (l, u) in zip(lower, upper)]
    widths = [u-l for (l, u) in zip(lower, upper)]
    volume = *(widths...)
    SearchBox(volume, lower, upper, bounds, widths)
end
Base.eltype(::SearchBox{T, <:Any, <:Any, <:Any, <:}) where T = T
function mlsl(obj, L, lower, upper; N, sigma, try_ratio, maxiter, getmin, getminf, partype=Sequential(), try_center=true)

    sbox = SearchBox(lower, upper)

    T = eltype(lower)
    n = length(lower)

    X, fX, Xfrom, fXfrom, star = initial_arrays(L, obj, sbox, try_center, getmin, getminf)

    for k = 1:maxiter
        rk = rₖ(T, n, k, N, sbox, sigma)
        nbest = try_ratio*k*N
        nbest = ceil(Int, nbest) # since try_ratio<1.0 we can safely round up
        X, fX = reduced_set!(fX, X, partype, sbox, obj, N)
        Xr, fXr = X[1:nbest], fX[1:nbest]
        for (xsearch, fxsearch) in zip(Xr, fXr)
            # Only start a search if xsearch is not in a cluster
            if !in_cluster(star, xsearch, fxsearch, rk)
                lxr = L(obj, lower, upper, xsearch)

                Xfrom, fXfrom, star = update_arrays!(fXfrom, Xfrom, star,
                 xsearch, fxsearch, getmin(lxr), getminf(lxr))
         end
        end
    end
    star.X, star.fX, Xfrom, fXfrom
end
function initial_arrays(L, obj, sbox, try_center, getmin, getminf)
    if try_center
        center = [l+(u-l)/2 for (l, u) in zip(sbox.lower, sbox.upper)]
        obj_center = obj(center)
        fXfrom = [obj_center]
        Xfrom = [center]
        X = [center]
        fX = [obj_center]
        lxr = L(obj, sbox.lower, sbox.upper, center)
        Xstar = [getmin(lxr)]
        fXstar = [getminf(lxr)]
    else
        # These and the accompanying methods allow for full inferrability of the
        # arrays and of the code in the main loop with the methods defined below.
        X = nothing
        fX = nothing
        Xfrom = nothing
        fXfrom = nothing
        Xstar = nothing
        fXstar = nothing
    end
    X, fX, Xfrom, fXfrom, (X=Xstar, fX=fXstar)
end
function update_arrays!(fXfrom::Nothing, Xfrom::Nothing, star, xsearch, fxsearch, lxr_minx, lxr_min)
    return [xsearch], [fxsearch], (X=[lxr_minx], fX=[lxr_min])
end
function update_arrays!(fXfrom, Xfrom, star, xsearch, fxsearch, lxr_minx, lxr_min)
    push!(fXfrom, fxsearch)
    push!(Xfrom, xsearch)
    push!(star.X, lxr_minx)
    push!(star.fX, lxr_min)
    return Xfrom, fXfrom, star
end

in_cluster(star::T, xsearch, fxsearch, rk) where T <: NamedTuple{<:Any, Tuple{Nothing, Nothing}} = false
function in_cluster(star, xsearch, fxsearch, rk)
    break_now = false
    for (x, fx) in zip(star.X, star.fX)
        is_close = norm(xsearch-x) <= rk
        Δf = fxsearch - fx
        is_larger = fxsearch >= fx
        if is_close && is_larger
            break_now = true
        end
        if break_now
            return true
        end
    end
    false
end

function reduced_set!(fX::Nothing, X::Nothing, partype, sbox, obj, N)
    # should do this in a sorted way
    X = sample_N(sbox.bounds, N)
    fX = obj.(X)
    p = sortperm(fX)
    X .= X[p]
    fX .= fX[p]
    X, fX
end
function reduced_set!(fX, X, partype, sbox, obj, N)
    # should do this in a sorted way
    Xnew = sample_N(sbox.bounds, N)
    push!(X, Xnew...)
    fXnew = obj.(Xnew)
    push!(fX, fXnew...)
    p = sortperm(fX)
    X .= X[p]
    fX .= fX[p]
    X, fX
end
function sample_N(bounds, N)
    [[rand()*(u-l)+l for (l, u) in bounds] for i = 1:N]
end
function rₖ(T, n, k, N, sbox, sigma)
    V = sbox.volume
    1/√T(π)*(gamma(T(1)+T(n)/2)*V*(sigma*log(k*N)/k*N))^(1/T(n))
end

end # module


text:
@testset "Paths" begin
  grid = RegularGrid{Float64}(100,100)

  for path in [LinearPath(grid), RandomPath(grid)]
    @test length(path) == 100*100
  end

  @testset "LinearPath" begin
    path = LinearPath(grid)
    @test collect(path) == collect(1:100*100)
  end

  @testset "RandomPath" begin
    path = RandomPath(grid)
    @test all(1 .≤ collect(path) .≤ 100*100)
  end

  @testset "SourcePath" begin
    grid = RegularGrid{Float64}(3,3)
    pset = PointSet(coordinates(grid))

    for sdomain in [grid, pset]
      path = SourcePath(sdomain, [1,9])
      @test collect(path) == [1,9,2,4,6,8,5,3,7]

      path = SourcePath(sdomain, [1])
      @test collect(path) == [1,2,4,5,3,7,6,8,9]
    end
  end

  @testset "ShiftedPath" begin
    path = LinearPath(RegularGrid{Float64}(3,3))
    @test collect(ShiftedPath(path,  0)) == collect(1:9)
    @test collect(ShiftedPath(path,  1)) == vcat(collect(2:9), [1])
    @test collect(ShiftedPath(path, -1)) == vcat([9], collect(1:8))
    @test length(ShiftedPath(path,  0)) == 9
    @test length(ShiftedPath(path,  1)) == 9
    @test length(ShiftedPath(path, -1)) == 9
  end
end


text:
"""
    permutation(n, r)

    returns the number of ways to choose r items from n items
    with order and without repetition

# Arguments:
- `n`: Positive integers of items to choose from
- 'r': Positive integers of items to choose

Contributed By:- [Mayur Dahibhate](https://github.com/mayurdahibhate)
"""

function permutation(n, r)
    function factorial(n)
        fact = 1

        if n == 0 || n == 1
            return fact
        end

        for i in 1:n
            fact = fact * i
        end

        return fact
    end

    perm = factorial(n) / factorial(n - r)

    return convert(Int64, perm)
end

max_issues_repo_name: AugustoCL/Julia

max_forks_repo_name: AugustoCL/Julia


text:
"""
This struct contains data for the operating reserve product
parameterized by the reserve direction (up or down).
    name: ReserveUp or ReserveDown.
    max_limit: Maximum percentage of reserve that can be provided by the project.
    marginal_cost: Marginal cost per unit of reserve provided.
"""
struct OperatingReserve{T <: ReserveDirection} <: ReserveEMIS{T}
    name::Symbol
    max_limit::Float64
    marginal_cost::Float64
end

get_max_limit(prod::OperatingReserve) = prod.max_limit


text:
# using Z3
using DReal
using Distributions
import Base.getindex
import Base:call

# If we're going row wise, the number of rows should change.
typealias NodeId Integer
typealias Weight Union(Real, DReal.Ex)
typealias NodeWeight Tuple{Integer, Weight}

"A layered neural network is a graph with edges only between layers"
immutable NeuralNetwork
  layersizes::Vector{Int}
  in_edge::Dict{NodeId, Vector{NodeWeight}}
end

weights(nn::NeuralNetwork) = [x[2] for x in values(nn.in_edge)]
nlayers(nn::NeuralNetwork) = length(nn.layersizes)

function nodesinlayer(nn::NeuralNetwork, l::Integer)
  lower = sum([nn.layersizes[i] for i=1:l-1]) + 1
  upper = lower + nn.layersizes[l] - 1
  collect(lower:upper)
end

"""Constructs a connected neural network where each node in layers 2 and above,
is randomly connected to `nchildren` from previous layer"""
function NeuralNetwork(layersizes::Vector{Int}, nchildren::Int)
  nn = NeuralNetwork(layersizes, Dict())
  for i = 2:nlayers(nn)
    nodeids = nodesinlayer(nn, i)
    prevlayer = nodesinlayer(nn, i-1)
    for nodeid in nodeids
      # Sample
      childrenids = sample(prevlayer, nchildren, replace=false)
      for childid in childrenids
        if haskey(nn.in_edge, nodeid)
          # Weights
          push!(nn.in_edge[nodeid], (childid, Var(Float64, 0.0, 10.)))
        else
          # Weights
          nn.in_edge[nodeid] = [(childid, Var(Float64, 0.0, 10.0))]
        end
      end
    end
  end
  nn
end

"Apply a Neural Network to a vector of inputs"
function call{T<:Real}(nn::NeuralNetwork, x::Vector{T})
  # Input size should math the row size
  @assert length(x) == nn.layersizes[1]
  # Initialise first row with input
  interm_values = Dict{Int, Any}([i => x[i] for i=1:nn.layersizes[1]])
  for i = 2:nlayers(nn)
    nodeids = nodesinlayer(nn, i)
    for nodeid in nodeids
      weighted_children = nn.in_edge[nodeid]
      weighted_input = [interm_values[nodeid] * weight for (nodeid, weight) in weighted_children]
      summed = sum(weighted_input)
      output = rectifier(summed)
      interm_values[nodeid] = output
    end
  end

  outputnodes = nodesinlayer(nn, nlayers(nn))

  # Output last row
  [interm_values[i] for i in outputnodes]
end

"Rectifier Unit"
# rectifier(x::Weight) = ifelse(x<0, 0.0, x)

rectifier(x) = 1.0 + exp(x)

function sqrdist(x::Array, y::Array)
  @assert length(x) == length(y)
  sum([(x[i] - y[i])^2 for i = 1:length(x)])
end

# Exmple
## ====
# Create a neural network
nn = NeuralNetwork([3,4,3,1], 2)

# Generate data and build objective function
ndata = 5
dists = DReal.Ex[]
for i = 1:ndata
  input = [rand() for i = 1:3]
  output = sum(input)
  push!(dists, sqrdist(nn(input), [output]))
end

cost = Var(Float64,0.0, 100.0)
add!(cost == sum(dists))
w = collect(values(nn.in_edge))[1][1][2]
minimize(cost, w; lb=0.0, ub=100.0)


text:
export Adam

"""
    Adam

Adam Optimizer

# References
* Kingma and Ba, ["Adam: A Method for Stochastic Optimization"](http://arxiv.org/abs/1412.6980v8), ICLR 2015.
"""
mutable struct Adam
    alpha::Float64
    beta1::Float64
    beta2::Float64
    eps::Float64
    states::IdDict
end

Adam() = Adam(0.001, 0.9, 0.999, 1e-8, IdDict())
Adam(alpha)= Adam(alpha, 0.9, 0.999, 1e-8, IdDict())

function (opt::Adam)(param::Array{T}, grad::Array{T}) where T
    @assert length(param) == length(grad)
    state = get!(opt.states, param, nothing)
    if state == nothing
        m, v, t = zeros(param), zeros(grad), 1
    else
        m::Array{T}, v::Array{T}, t::Int = state
    end
    BLAS.scale!(T(opt.beta1), m)
    BLAS.axpy!(T(1.0 - opt.beta1), grad, m)
    BLAS.scale!(T(opt.beta2), v)
    @inbounds for i = 1:length(grad)
        grad[i] = grad[i] * grad[i]
    end
    BLAS.axpy!(T(1.0 - opt.beta2), grad, v)
    fix1 = 1.0 - opt.beta1 ^ t
    fix2 = 1.0 - opt.beta2 ^ t
    rate = opt.alpha * sqrt(fix2) / fix1
    @inbounds for i = 1:length(param)
        param[i] -= rate * m[i] / (sqrt(v[i]) + T(opt.eps))
    end
    opt.states[param] = (m, v, t + 1)
    fill!(grad, T(0.0))
end
(opt::Adam)(x::Var) = opt(x.data, x.grad)

function update_slow!(opt::Adam, param::Array{T}, grad::Array{T}) where T
    state = get!(opt.states, param, nothing)
    if state == nothing
        m, v, t = zeros(param), zeros(grad), 1
    else
        m::Array{T}, v::Array{T}, t::Int = state
    end
    m += (1.0 - opt.beta1) * (grad - m)
    v += (1.0 - opt.beta2) * (grad .* grad - v)
    fix1 = 1.0 - opt.beta1 ^ t
    fix2 = 1.0 - opt.beta2 ^ t
    rate = opt.alpha * sqrt(fix2) / fix1
    for i = 1:length(param)
        param[i] -= rate * m[i] / (sqrt(v[i]) + T(opt.eps))
    end
    opt.states[param] = (m, v, t + 1)
    fill!(grad, T(0.0))
end


text:
# function POMDPs.initialize_belief(pomdp::SingleOCPOMDP)
#     b0 = DiscreteBelief(n_states(pomdp))
#     d0 = initialstate_distribution(pomdp::SingleOCPOMDP)
#     for (i, s) in enumerate(iterator(states(pomdp)))
#         b0.b[i] = pdf(d0, s)
#     end
#     @assert sum(b0.b) ≈ 1.0
#     return b0
# end

#for sarsop for exploration
# function POMDPs.initialstate_distribution(pomdp::SingleOCPOMDP)
#      state_space = states(pomdp)
#      states_to_add = SingleOCState[]
#      for s in state_space
#          if !s.crash
#              push!(states_to_add, s)
#          end
#      end
#      probs = ones(length(states_to_add))
#      normalize!(probs, 1)
#      return SparseCat(states_to_add, probs)
#  end

"""
Returns the initial state of the pomdp problem
"""
function POMDPs.initialstate(pomdp::SingleOCPOMDP, rng::AbstractRNG)
    ped = rand(rng) > pomdp.no_ped_prob
    if ped
        pomdp.no_ped = false
        d = initialstate_distribution(pomdp)
        s = rand(rng, d)
    else
        # println("No pedestrians")
        pomdp.no_ped = true
        d = initial_distribution_no_ped(pomdp::SingleOCPOMDP)
        s = rand(rng, d)
    end
    return s
end

"""
Returns the initial state distribution over the ego car state when there is no pedestrians
"""
function initial_distribution_no_ped(pomdp::SingleOCPOMDP)
    env = pomdp.env
    V_ego = LinRange(0., env.params.speed_limit, Int(floor(env.params.speed_limit/pomdp.vel_res)) + 1)
    rl = env.params.roadway_length
    cw = env.params.crosswalk_width
    lw = env.params.lane_width
    cl = env.params.crosswalk_length
    p_birth = pomdp.p_birth
    x_ped = 0.5*(env.params.roadway_length - env.params.crosswalk_width + 1)
    y_ego = 0. #XXX might need to be a parameter
    x_start = pomdp.x_start #XXX parameterized
    states = SingleOCState[]
    for v in V_ego
        ego = VehicleState(VecSE2(x_start, y_ego, 0.), env.roadway, v)
        push!(states, SingleOCState(false, ego, get_off_the_grid(pomdp)))
    end
    probs = ones(length(states))
    probs = normalize!(probs, 1)
    return SparseCat(states, probs)
end

function POMDPs.initialstate_distribution(pomdp::SingleOCPOMDP)
    env = pomdp.env
    V_ego = LinRange(0., env.params.speed_limit, Int(floor(env.params.speed_limit/pomdp.vel_res)) + 1)
    rl = env.params.roadway_length
    cw = env.params.crosswalk_width
    lw = env.params.lane_width
    cl = env.params.crosswalk_length
    p_birth = pomdp.p_birth
    x_ped = 0.5*(env.params.roadway_length - env.params.crosswalk_width + 1)
    y_ego = 0. #XXX might need to be a parameter
    x_start = pomdp.x_start #XXX parameterized
    Y = get_Y_grid(pomdp)
    V_ped = LinRange(0, env.params.ped_max_speed, Int(floor(env.params.ped_max_speed/pomdp.vel_res)) + 1)
    states = SingleOCState[]
    for v in V_ego
        ego = VehicleState(VecSE2(x_start, y_ego, 0.), env.roadway, v)
        for y in Y[1:div(length(Y),2)]
            for v_ped in V_ped
                ped = VehicleState(VecSE2(x_ped, y, pi/2), env.roadway, v_ped)
                crash = is_colliding(Vehicle(ego, pomdp.ego_type, 0),
                                     Vehicle(ped, pomdp.ped_type, 1))
                push!(states, SingleOCState(crash, ego, ped))
            end
        end
    end
    # Add also the off the grid state, weight using the probability p_birth
    # of a pedestrian actually being here
    n_in_grid = length(states)
    for v in V_ego
        ego = VehicleState(VecSE2(x_start, y_ego, 0.), env.roadway, v)
        push!(states, SingleOCState(false, ego, get_off_the_grid(pomdp)))
    end
    n_off_grid = length(states) - n_in_grid
    probs = ones(length(states))
    probs[1:n_in_grid] .= p_birth/n_in_grid
    probs[n_in_grid + 1:end] .= (1.0 - p_birth)/n_off_grid
    normalize!(probs, 1)
    @assert sum(probs) ≈ 1.
    return SparseCat(states, probs)
end

function POMDPs.initialstate_distribution(pomdp::SingleOCPOMDP, ego::VehicleState)
    env = pomdp.env
    rl = env.params.roadway_length
    cw = env.params.crosswalk_width
    lw = env.params.lane_width
    cl = env.params.crosswalk_length
    p_birth = pomdp.p_birth
    x_ped = 0.5*(env.params.roadway_length - env.params.crosswalk_width + 1)
    y_ego = 0. #XXX might need to be a parameter
    x_start = pomdp.x_start #XXX parameterized
    Y = get_Y_grid(pomdp)
    V_ped = LinRange(0, env.params.ped_max_speed, Int(floor(env.params.ped_max_speed/pomdp.vel_res)) + 1)
    states = SingleOCState[]
    for y in Y[1:div(length(Y),2)]
        for v_ped in V_ped
            ped = VehicleState(VecSE2(x_ped, y, pi/2), env.roadway, v_ped)
            crash = is_colliding(Vehicle(ego, pomdp.ego_type, 0),
                                 Vehicle(ped, pomdp.ped_type, 1))
            push!(states, SingleOCState(crash, ego, ped))
        end
    end
    # Add also the off the grid state, weight using the probability p_birth
    # of a pedestrian actually being here
    n_in_grid = length(states)
    push!(states, SingleOCState(false, ego, get_off_the_grid(pomdp)))

    n_off_grid = length(states) - n_in_grid
    probs = ones(length(states))
    probs[1:n_in_grid] = p_birth/n_in_grid
    probs[n_in_grid + 1:end] = (1.0 - p_birth)/n_off_grid
    # normalize!(probs, 1)
    @assert sum(probs) ≈ 1.
    return SparseCat(states, probs)
end

mutable struct SingleOCUpdater <: Updater
    pomdp::SingleOCPOMDP
end

# Updates the belief given the current action and observation
function POMDPs.update(bu::SingleOCUpdater, bold::SparseCat, a::SingleOCAction, o::SingleOCObs)
    bnew = SparseCat(SingleOCState[], Float64[])
    pomdp = bu.pomdp
    # initialize spaces
    pomdp_states = ordered_states(pomdp)

    # iterate through each state in belief vector
    for (i, sp) in enumerate(pomdp_states)
        # get the distributions
        od = observation(pomdp, a, sp)
        # get prob of observation o from current distribution
        probo = pdf(od, o)
        # if observation prob is 0.0, then skip rest of update b/c bnew[i] is zero
        if probo == 0.0
            continue
        end
        b_sum = 0.0 # belief for state sp
        for (j, s) in enumerate(bold.vals)
            td = transition(pomdp, s, a)
            pp = pdf(td, sp)
            b_sum += pp * bold.probs[j]
        end
        if b_sum != 0.
            push!(bnew.it, sp)
            push!(bnew.p, probo*b_sum)
        end
    end

    # if norm is zero, the update was invalid - reset to uniform
    if sum(bnew.p) == 0.0
        println("Invalid update for: ", bold, " ", a, " ", o)
        throw("UpdateError")
    else
        normalize!(bnew.p, 1)
    end
    bnew
end

########################### HELPERS ###############################################################

# These functions are helpful to reshape the belief as input of a deep RL algorithm

"""
    vec2dis(bvec::Vector{Float64}, state_space::Vector{SingleOCState} = state_space)
Convert a discrete belief representation to a more compact one using the SparseCat type
"""
function vec2dis(bvec::Vector{Float64}, state_space::Vector{SingleOCState} = state_space)
    bsparse = sparsevec(bvec)
    n = nnz(bsparse)
    bdis = SparseCat(Vector{SingleOCState}(n), zeros(n))
    for i = 1:n
        ind = bsparse.nzind[i]
        bdis.p[i] = bsparse.nzval[i]
        bdis.it[i] = state_space[ind]
    end
    return bdis
end

"""
    dis2vec!(pomdp::SingleOCPOMDP, bdis::SparseCat, bvec::Vector{Float64})
convert an SparseCat to a full vector representation
"""
function dis2vec!(pomdp::SingleOCPOMDP, bdis::SparseCat, bvec::Vector{Float64})
    for i =1:length(bdis.probs)
        ind = stateindex(pomdp, bdis.vals[i])
        bvec[ind] = bdis.p[i]
    end
end

"""
    get_belief_image(pomdp::SingleOCPOMDP, d0::SparseCat, Y::LinRange{Float64} = get_Y_grid(pomdp), V_ped::LinRange{Float64} = get_V_ped_grid(pomdp))
returns a probability matrix where the index are the pedestrian position and velSingleOCity, the values are the probability of such y,v pair
"""
function get_belief_image(pomdp::SingleOCPOMDP, d0::SparseCat, Y::LinRange{Float64} = get_Y_grid(pomdp), V_ped::LinRange{Float64} = get_V_ped_grid(pomdp))
    Y = get_Y_grid(pomdp)
    V_ped = get_V_ped_grid(pomdp)
    P = zeros(length(Y), length(V_ped))
    p_off_grid = 0.
    for (i,s) in enumerate(d0.vals)
        if off_the_grid(pomdp, s.ped)
            p_off_grid += d0.probs[i]
        else
            y_ind = get_y_index(pomdp, s.ped.posG.y)
            v_ped_ind = get_v_ped_index(pomdp, s.ped.v)
            P[y_ind, v_ped_ind] += d0.probs[i]
        end
    end
    @assert sum(P) + p_off_grid ≈ 1.0
    return P, p_off_grid
end

"""
    tuple_to_belief(pomdp::SingleOCPOMDP, t::Tuple{Array{Float64,1},Array{Float64,2}})
convert tuple representation to SparseCat object
"""
function tuple_to_belief(pomdp::SingleOCPOMDP, t::Tuple{Array{Float64,1},Array{Float64,2}})
    Y_grid = get_Y_grid(pomdp)
    V_ped = get_V_ped_grid(pomdp)
    b = SparseCat(SingleOCState[], Float64[])
    P = t[2]
    ego_x, ego_v, p_off = t[1][1], t[1][2], t[1][3]
    ego = xv_to_state(pomdp, ego_x, ego_v)
    m, n = size(P)
    for i=1:n
        for j=1:m
            if P[j, i] != 0
            ped = yv_to_state(pomdp, Y_grid[j], V_ped[i])
            s = SingleOCState(collision_checker(ego, ped, pomdp.ego_type, pomdp.ped_type), ego, ped)
            push!(b.vals, s)
            push!(b.probs, P[j, i])
            end
        end
    end
    s_off = SingleOCState(false, ego, get_off_the_grid(pomdp))
    push!(b.vals, s_off)
    push!(b.probs, p_off)
    # sanity check
    @assert sum(b.p) ≈ 1.0
    @assert length(b.p) == length(b.it)
    return b
end

"""
    belief_to_tuple(pomdp::SingleOCPOMDP, b::SparseCat)
only valid after first step when ego car is known
convert a belief representation into a tuple [ego.x, ego.v, p_off], belief image
"""
function belief_to_tuple(pomdp::SingleOCPOMDP, b::SparseCat)
    vec = zeros(3)
    ego_x, ego_v = b.it[1].ego.posG.x, b.it[1].ego.v
    img, p_off = get_belief_image(pomdp, b, get_Y_grid(pomdp), get_V_ped_grid(pomdp))
    vec[1], vec[2], vec[3] = ego_x, ego_v, p_off
    s = (vec, img)
end

max_stars_repo_name: MaximeBouton/AutomotivePOMDPs

max_issues_repo_name: MaximeBouton/AutomotivePOMDPs

max_forks_repo_name: MaximeBouton/AutomotivePOMDPs


text:
function eg1()
    z = eg2(2)
    eg_last(z)
end

eg_last(x) = x

function eg2(x)
    y=eg21(x)
    ret = eg3(x,y)
    y = 1 + y
    return ret
end

eg21(x) = 2x

function eg3(a,b)
    a+b
end
############

function egerr()
    egerr2(2)
end

function egerr2(x)
    y=2x
    egerr3(x,y)
end

function egerr3(a,b)
    error(a)
end


text:
using CxxWrap
using Base.Test

wrap_modules(CxxWrap._l_containers)
using Containers

@test test_tuple() == (1,2.0,3.0f0)

cptr = const_ptr()
@test isbits(typeof(cptr))
@test const_ptr_arg(cptr) == (1., 2., 3.)

cv = const_vector()
@test size(cv) == (3,)
@test cv == [1.,2.,3.]

cm = const_matrix()
@test size(cm) == (3,2)
@test cm == [[1.,2.,3.] [4.,5.,6.]]
println("Displaying const matrix")
display(cm)
println("")


text:
using SeniorProjectAssignments
using Test
using DataFrames
using CSV

using SeniorProjectAssignments: match

@testset "SeniorProjectAssignments.jl" begin

students = [
    StudentData("Alice",
                (software=0.9, hardware=0.1, electronics=0.0),
                false,
                ["Airplane", "Rocket"]
               ),
    StudentData("Bob",
                (software=0.1, hardware=0.9, electronics=0.0),
                true,
                ["Rocket", "Airplane"]
               ),
    StudentData("Charlie",
                (hardware=0.9, software=0.1, electronics=0.0),
                true,
                ["Airplane", missing]
               )
]

projects = [
            ProjectData("Airplane", (hardware=1.0, software=1.0), 2, 3),
            ProjectData("Rocket", (hardware=0.8,), 1, 2)
]

@show match(students, projects, [])

groups = [["Alice", "Bob"]]
@show match(students, projects, groups)

@show match(students, projects, [], force=["Bob"=>"Airplane"])

# survey_dataframe = CSV.read("../data/section012.csv", DataFrame, header=1, datarow=4)
# project_dataframe = CSV.read("../data/projects_011.csv", DataFrame)
#
# projects = process_projects(project_dataframe)
# @show pnames = [p.id for p in projects]
# students, groups = process_survey(survey_dataframe, pnames)

end


text:
mutable struct FiniteCMPS{T<:MatrixFunction, N, V<:AbstractVector} <: AbstractCMPS{T,N}
    Q::T
    Rs::NTuple{N,T}
    vL::V
    vR::V
    function FiniteCMPS(Q::T, Rs::NTuple{N,T}, vL::V, vR::V) where {T,N,V}
        for R in Rs
            domain(Q) == domain(R) || throw(DomainMismatch())
        end
        (a,b) = domain(Q)
        Qa = Q(a)
        length(vL) == length(vR) == size(Qa,1) == size(Qa,2) || throw(DimensionMismatch())
        for R in Rs
            size(R(a)) == size(Qa) || throw(DimensionMismatch())
        end
        return new{T,N,V}(Q, Rs, vL, vR)
    end
end
FiniteCMPS(Q::T, R::T, vL::V, vR::V) where {T,V} = FiniteCMPS(Q, (R,), vL, vR)

domain(Ψ::FiniteCMPS) = domain(Ψ.Q)

Base.iterate(Ψ::FiniteCMPS, args...) = iterate((Ψ.Q, Ψ.Rs, Ψ.vL, Ψ.vR), args...)

Base.copy(Ψ::FiniteCMPS) = FiniteCMPS(copy(Ψ.Q), copy.(Ψ.Rs), copy(Ψ.vL), copy(Ψ.vR))

Base.:(==)(Ψ1::FiniteCMPS, Ψ2::FiniteCMPS) =
    Ψ1.Q == Ψ2.Q && Ψ1.Rs == Ψ2.Rs && Ψ1.vL == Ψ2.vL && Ψ1.vR == Ψ1.vR


text:
# TODO remove broadcasts where possible

println("\n\n\nStarting runtests.jl $(join(ARGS, " ")) ...")

using Test, FunctionalData

macro shouldtestset(a,b) length(ARGS) < 1 || ARGS[1] == a ?  :(@testset $a $b) : nothing end
macro shouldtestset2(a,b) length(ARGS) < 2 || ARGS[2] == a ?  :(@testset $a $b) : nothing end

mutable struct A
    a
    b
end

function checkcodeexamples(filename)
    absname = @p functionloc checkcodeexamples | fst | dirname | joinpath "../doc/"*filename
    mdlines = @p read absname String | lines

    startasserts = true
    insidecode = false

    for line in mdlines
        isempty(strip(line)) && continue
        if startswith(line, "```jl")
            insidecode = true && startasserts
        elseif startswith(line, "```")
            insidecode = false
        elseif insidecode
            # println(line)
            if occursin("=>", line)
                line = @p split line "=>" | concat "@test (" fst(_) ")  ==  (" snd(_) ")"
            end
            eval(Meta.parse(line))
        end
    end
end

@shouldtestset "doc" begin
    @shouldtestset2 "computing" begin
        checkcodeexamples("computing.md")
    end
    @shouldtestset2 "dataflow" begin
        checkcodeexamples("dataflow.md")
    end
    @shouldtestset2 "helpers" begin
        checkcodeexamples("helpers.md")
    end
    @shouldtestset2 "io" begin
        checkcodeexamples("io.md")
    end
    @shouldtestset2 "lensize" begin
        checkcodeexamples("lensize.md")
    end
    @shouldtestset2 "output" begin
        checkcodeexamples("output.md")
    end
    @shouldtestset2 "pipeline" begin
        checkcodeexamples("pipeline.md")
    end
end

@shouldtestset "views" begin
    a = [1,2,3]
    @test FD.view(a,1)  ==  [1]
    @test FD.view(a,3)  ==  [3]
    a = [1 2 3]
    @test FD.view(a,1)  ==  row([1])
    @test FD.view(a,3)  ==  row([3])
    a = [1 2 3; 4 5 6]
    @test FD.view(a,1)  ==  col([1,4])
    @test size(FD.view(a,1))  ==  (2,1)
    @test FD.view(a,3)  ==  col([3,6])
    v = FD.view(a,2)
    v[2] = 10
    @test a == [1 2 3; 4 10 6]
    a = UInt8[1 2 3; 4 5 6]
    @test FD.view(a,1)  ==  col(UInt8[1,4])
    @test FD.view(a,3)  ==  col(UInt8[3,6])
    @test FD.view(a,2:3)  == part(a,2:3)
    @test size(FD.view(a,2:3))  == (2,2)
    @test size(FD.view(rand(2,3,4),1)) == (2,3)
    @test size(FD.view(rand(2,3,4),1:2)) == (2,3,2)

    @shouldtestset2 "read!" begin
        a = UInt8[1 2 3]
        v = FD.view(a,2)
        data = IOBuffer(UInt8[0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
        read!(data, v)
        @test a == [1 0 3]
        a = UInt8[1 2 3; 4 5 6]
        v = FD.view(a,2)
        data = IOBuffer(UInt8[0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
        read!(data, v)
        @test a == [1 0 3; 4 0 6]
        a = UInt8[1 2 3; 4 5 6]
        v = FD.view(a,2:3)
        data = IOBuffer(UInt8[0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
        read!(data, v)
        @test a == [1 0 0; 4 0 0]
        a = ones(UInt8, 2, 3, 4)
        v = FD.view(a,2)
        data = IOBuffer(UInt8[0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
        read!(data, v)
        @test a == cat(ones(UInt8,2,3), zeros(UInt8,2,3), ones(UInt8,2,3), ones(UInt8,2,3), dims=3)
    end
end

@shouldtestset "lensize" begin
    @test siz(1)      ==  transpose([1 1])
    @test siz([1])    ==  transpose([1 1])
    @test siz([1,2])  ==  transpose([2 1])
    @test siz([1;2])  ==  transpose([2 1])
    @test siz([1 2])  ==  transpose([1 2])
    @test siz(transpose([1 2]))  ==  transpose([2 1])

    @test siz3(rand(1))  == [1 1 1]'
    @test siz3(rand(1,2))  == [1 2 1]'
    @test siz3(rand(1,2,3))  == [1 2 3]'

    @test len(1)        ==  1
    @test len([1])      ==  1
    @test len([1,2])    ==  2
    @test len([1;2])    ==  2
    @test len([1 2])    ==  2
    @test len([1,2,3])  ==  3
    @test len([1 1 1 ;2 2 3])  ==  3
    @test len("adsf")   ==   4
    @test len('a')      ==  1
    @test len(['a',1])  ==  2
end

@shouldtestset "basics" begin
    @shouldtestset2 "arraylike" begin
        @test size(FunctionalData.arraylike([1],2)) == (1,2)
        @test size(FunctionalData.arraylike([1 2],2)) == (1,2,2)
        @test size(FunctionalData.arraylike(1,2)) == (2,)
    end
    @shouldtestset2 "ones" begin
        @test onessiz([2 3 4]') == ones(2,3,4)
        @test zerossiz([2 3 4]') == zeros(2,3,4)
        @test size(randsiz([2 3 4]')) == (2,3,4)
        @test size(randnsiz([2 3 4]')) == (2,3,4)
    end
    @shouldtestset2 "shones" begin
        @test shonessiz([2 3 4]') == ones(2,3,4)
        @test shzerossiz([2 3 4]') == zeros(2,3,4)
        @test size(randsiz([2 3 4]')) == (2,3,4)
        @test size(randnsiz([2 3 4]')) == (2,3,4)
    end
    @shouldtestset2 "repeat" begin
        @test repeat('a',0) == ""
        @test repeat('a',1) == "a"
        @test repeat('a',3) == "aaa"
        @test repeat("a",0) == ""
        @test repeat("a",1) == "a"
        @test repeat("a",3) == "aaa"
        @test repeat(1,3)  == [1,1,1]
        @test repeat([1],3) == [1,1,1]
        @test repeat([1 2]',3) == [1 1 1; 2 2 2]
    end
    @shouldtestset2 "minimum" begin
        @test minimum(Float32)+maximum(Float32) == 0f0
        @test minimum(Float64)+maximum(Float64) == 0.0
        @test minimum(Int)+maximum(Int) == -1
        @test maximum() == maximum(Float64)
        @test minimum() == minimum(Float64)
    end
end

mutable struct _somedummytype
    a
    b
end

@shouldtestset "accessors" begin
    @shouldtestset2 "at" begin
        @test at([1,2,3],1) == 1
        @test at([1 2 3],1) == col([1])
        @test at([1;2;3],1) == 1
        @test at((1,2,3),1) == 1
        @test at([1 2 3; 4 5 6],1) == col([1 4])
        @test at(cat([1 1],[2 2],[3 3],dims=3),1) == [1 1]

        @test at("asdf",1) == 'a'
        @test at(Any["aa",1],1) == "aa"
        @test at(['a','b'],2) == 'b'
        @test at(['a','b'],1) == 'a'

        # @test size(at(rand(2,3,4),(1,))) == ()
        # @test size(at(rand(2,3,4),(1:2,))) == (2,)
        # @test size(at(rand(2,3,4),([1,2],1:2))) == (2,2)

        d = Dict(:a => 1, :b => Dict(:c => 2, :d => Dict(:e => 3)))
        @test at(d,:a) == 1
        @test at(d,:b,:c) == 2
        @test at(d,:b,:c) == 2
        @test at(d,:b,:d,:e) == 3
    end
    @shouldtestset2 "atend" begin
        @test atend(1:10,1) == 10
        @test atend(1:10,2) == 9
    end

    @shouldtestset2 "setat" begin
        a = [1,2,3]
        setat!(a, 1, 10)
        @test at(a,1) == 10
        a = [1 2 3]
        setat!(a, 1, 10)
        @test at(a,1) == col([10])
        setat!(a, 1, col([10]))
        @test at(a,1) == col([10])
        a = [1 2 3; 4 5 6]
        setat!(a, 1, col([10,11]))
        @test at(a,1) == col([10,11])
        a = cat([1 1],[2 2],[3 3],dims=3)
        setat!(a,1,[10 11])
        @test at(a,1) == [10 11]

        a = Any["aa",1]
        setat!(a, 1, "bb")
        @test at(a,1) == "bb"
    end

    @shouldtestset2 "part" begin
        @test part([1,2,3],[1])  == [1]
        @test part([1,2,3],1:2) == [1,2]
        @test part([1,2,3],[1,2]) == [1,2]
        @test part([1 2 3],[1,3]) == [1 3]
        @test part([1 2 3],[1,3]) == selectdim([1 2 3],2,[1,3])
        @test part([1;2;3],[1,3]) == [1;3]
        @test part([1 2 3; 4 5 6],[1,3]) == [1 3;4 6]
        @test part([1 2 3; 4 5 6],[1 2; 3 2]) == [3,5]
    end

    @shouldtestset2 "dict" begin
        d = Dict(:a => 1, :b => 2)
        @test part(d, :a) == Dict(:a => 1)
        @test part(d, :a, :b) == d
        @test values(d, :a) == [1]
        # @test values(d, :a, :b) == [1,2]
        # @test values(A(1,2), :a, :b)  ==  [1,2]
    end

    @shouldtestset2 "trimmedpart" begin
        @test trimmedpart(collect(1:10), -1:3) == [1,2,3]
        @test trimmedpart(collect(1:10), 1:3) == [1,2,3]
        @test trimmedpart(collect(1:10), 8:13) == [8,9,10]
        @test trimmedpart(collect(1:10), 13:15) == []
        @test trimmedpart(1:10, [1,3,30,2,-10]) == [1,3,2]
    end

    @shouldtestset2 "fst" begin
        @test fst([1 2 3]) == col([1])
        @test fst(1:3) == 1
        @test fst([1 2 3; 4 5 6]) == col([1,4])
        @test fst('a') == 'a'
        @test fst("asdf") == 'a'
    end

    @shouldtestset2 "last" begin
        @test last([1 2 3]) == col([3])
        @test last(1:3) == 3
        @test last([1 2 3; 4 5 6]) == col([3,6])
        @test last('a') == 'a'
        @test last("asdf") == 'f'
    end

    @shouldtestset2 "drop" begin
        @test drop([1,2,3],1) == [2,3]
        @test drop(Any["test",2,"asdf"],1) == Any[2,"asdf"]
        @test drop(Any["test",2,"asdf"],2) == ["asdf"]

        @test drop(1:3,1) == 2:3
        @test drop([1 2 3],1) == [2 3]
        @test drop([1 2 3; 4 5 6],1) == [2 3; 5 6]
        @test drop([1 2 3; 4 5 6],2) == col([3; 6])
    end

    @shouldtestset2 "dropat" begin
        @test dropat(1:10,3:9) == [1,2,10]
    end

    @shouldtestset2 "take" begin
        @test take(1:3,1) == 1:1
        @test take([1 2 3],1) == col([1])
        @test take([1 2 3; 4 5 6],1) == col([1; 4])
        @test take([1 2 3; 4 5 6],2) == [1 2; 4 5]
        @test take("asdf",1) == "a"
        @test take("asdf",2) == "as"

        @test last(1:3,1) == 3:3
        @test last([1 2 3],1) == col([3])
        @test last([1 2 3; 4 5 6],1) == col([3; 6])
        @test last([1 2 3; 4 5 6],2) == [2 3; 5 6]
        @test last("asdf",1) == "f"
        @test last("asdf",2) == "df"
    end

    @shouldtestset2 "takelast" begin
        @test takelast("asdf",1) == "f"
        @test takelast("asdf",2) == "df"
        @test takelast("asdf",10) == "asdf"
    end

    @shouldtestset2 "takewhile" begin
        @test takewhile(1:10,x->x<5) == 1:4
        @test (@p takewhile (1:10) isless 5) == 1:4
        @test (@p takewhile (1:10) isless 50) == 1:10
        @test (@p takewhile (1:10) isless 0) == []
    end

    @shouldtestset2 "droplast" begin
        @test droplast(1:3,1) == 1:2
        @test droplast([1 2 3],1) == [1 2]
        @test droplast([1 2 3; 4 5 6],1) == [1 2 ; 4 5 ]
        @test droplast([1 2 3; 4 5 6],2) == col([1; 4])
        @test droplast([]) == []
        @test droplast([1]) == []
        @test droplast([],2) == []
    end

    @shouldtestset2 "dropwhile" begin
        @test dropwhile(1:10,x->x<5) == 5:10
        @test (@p dropwhile (1:10) isless 5) == 5:10
        @test (@p dropwhile (1:10) isless 50) == []
        @test (@p dropwhile (1:10) isless 0) == 1:10
    end

    @shouldtestset2 "cut" begin
        a = [1,2,3,4,5]
        b = [1 2 3; 4 5 6]
        @test cut(a,3)  ==  ([1,2,4,5],[3])
        @test cut(b,1)  ==  ([2 3; 5 6], col([1,4]))
        @test cut(b,2:3)  ==  (col([1,4]), [2 3; 5 6])
    end

    @shouldtestset2 "partition" begin
        @test partition(1:3,1)  == Any[1:3]
        # a = partition(1:3,2)
        # @test (a == Any[1:2, 3:3] || a == Any[1:1, 2:3])  ==  true  # Julia v0.3 and v0.4 work differently
        # @test partition(1:3,3)  == Any[1:1, 2:2, 3:3]
        # @test partition(1:3,4)  == Any[1:1, 2:2, 3:3]
    end

    @shouldtestset2 "partsoflen" begin
        # @test partsoflen(1:4,2)  ==  Any[1:2, 3:4]
        # @test partsoflen(1:4,3)  ==  Any[1:3, 4:4]
    end

    @shouldtestset2 "extract" begin
        @test extract(_somedummytype(1,2), :a)  ==  1
        @test extract(_somedummytype(1,2), :b)  ==  2
        @test extract([_somedummytype(1,2), _somedummytype(3,4)], :b)  ==  [2,4]
        d1 = Dict(:a => 1)
        d2 = Dict(:b => 2)
        @test extract(d1, :a)  ==  1
        @test extract(d1, :b)  ==  nothing
        @test extract([d1,d2], :a, 10)  ==  [1, 10]
    end
    @shouldtestset2 "extractnested" begin
        a = [Dict(:a => 1, :b => Dict(:c => 1)), Dict(:a => 2, :b => Dict(:c => 3))]
        @test extractnested(a,:b,:c) == Any[1,3]
    end
    @shouldtestset2 "fieldvalues" begin
        @test fieldvalues(A(1,2)) == [1,2]
        @test dict(A(1,2)) == Dict(:a => 1, :b => 2)
    end
    @shouldtestset2 "isnil" begin
        @test isnil(Nothing) == true
        @test isnil(nothing) == true
        @test isnil(1) == false
        @test isnil("asdf") == false
    end
end

@shouldtestset "computing" begin
    @shouldtestset2 "fold" begin
        @test fold([1,2,3], max)  ==  3
        @test fold(["1","2","3"], concat)  ==  "123"
    end
    @shouldtestset2 "sort" begin
        @test FunctionalData.sort([1,2,3], id) == [1,2,3]
        @test FunctionalData.sort([1 2 3], x->x[1]) == [1 2 3]
        @test FunctionalData.sort([1,2,3], x->-x) == [3,2,1]
        @test FunctionalData.sort([1 2 3], x->-x[1]) == [3 2 1]
        local D = [Dict(:id => x, :a => string(x)) for x in 1:3]
        @test FunctionalData.sort(D, :id) == D
        @test FunctionalData.sort("dcba", x->convert(Int,x)) == "abcd"
        @test FunctionalData.sort("dcba", x->convert(Int,x); rev = true) == "dcba"
        @test FunctionalData.sortrev("dcba", x->convert(Int,x)) == "dcba"
    end
    @shouldtestset2 "groupdict" begin
        a = [1,2,3,2,3,3]
        @test (@p groupdict a id) == Dict(1 => Any[1], 2 => Any[2,2], 3 => Any[3,3,3])
    end
    @shouldtestset2 "groupby" begin
        # a = ["a1","b1","c1","a2","b2","c2"]
        # @test (@p groupby a snd) == Any[Any["a1","b1","c1"],Any["a2","b2","c2"]]
        # a = [1,2,3,2,3,3]
        # @test (@p groupby a id) == Any[Any[1],Any[2,2],Any[3,3,3]]
        a = [2 1 3 2 3 3; 20 10 30 20 30 30]
        @test (@p groupby a getindex 2) == Any[col([1 10]), [2 2; 20 20], [3 3 3; 30 30 30]]
    end
    @shouldtestset2 "filter" begin
        @test filter([1,2,3],x->isodd(x)) == [1,3]
        @test filter([1,2,3],x->iseven(x)) == [2]
        @test (@p filter Any[1,2,3] unequal 3) == [1,2]
        @test (@p filter [1,2,3] unequal 3) == [1,2]
        @test (@p FD.select [1,2,3] unequal 3) == [1,2]
        @test (@p reject [1,2,3] unequal 3) == [3]
    end
    @shouldtestset2 "uniq" begin
        f(a) = abs.(a)
        @test uniq([10 20 30])  ==  [10 20 30]
        @test uniq([20 20 10], id)  ==  [20 10]
        @test uniq([20 -10 10], f)  ==  [20 -10]
        @test uniq([20 10 -10], f)  ==  [20 10]
        @test (@p uniq [20 10 -10] f)  ==  [20 10]
        @test (@p uniq [20 10 -10] getindex 1)  ==  [20 10 -10]
    end
    @shouldtestset2 "map" begin
        @test map([1 2 3; 4 5 6], x->[size(x,1)]) ==   [2 2 2]
        @test map([1 2 3; 4 5 6], x->Any[size(x,1)]) ==   Any[2 2 2]
        @test map([1 2 3; 4 5 6], x->[size(x,1);size(x,1)]) == [2 2 2; 2 2 2]
        @test map([1 2 3; 4 5 6], x->[size(x,1);size(x,1)]) == [2 2 2; 2 2 2]
        @test map([1 2 3; 4 5 6], x->[size(x,1) size(x,1)]) == cat([2 2],[2 2],[2 2],dims=3)
        @test map((Dict(1 => 2)), x->(fst(x), 10*snd(x))) == Dict(1 => 20)
        @test map((Dict(1 => 2)), x->nothing) == Dict()
        @test (@p map Dict(1 => 2) x->(fst(x), 10*snd(x))) == Dict(1 => 20)
        @test (@p map Dict(1 => 2) x->nothing) == Dict()

        @test map(Dict(1 => 2, 3 => 4), x->(fst(x),10*fst(x)+snd(x))) == Dict(1=>12,3=>34)

        @test mapdict(Dict(1 => 2), (k,v) -> (k,k+v)) == Dict(1 => 3)
        @test (@p mapdict (Dict(1 => 2)) (k,v) -> (k,k+v)) == Dict(1 => 3)
        @test mapdict(Dict(1 => 10, 2 => 20), (k,v) -> k == 1 ? (k,k+v) : nothing) == Dict(1 => 11)
        @test mapkeys((Dict(1 => 2)), x -> 2x) == Dict(2 => 2)
        @test mapvalues((Dict(1 => 2)), x -> 2x) == Dict(1 => 4)
        d = Dict(:a => 1, :b => 2)
        @test (@p mapmap d id | sort) == [1,2]
        @test (@p map (1:3) BigInt)  ==  BigInt[1,2,3]
        @test (@p map Any[1,2,3] BigInt)  ==  BigInt[1,2,3]
    end
    @shouldtestset2 "mapi" begin
        @test reduce(&, mapi(0:9, (x,i)->x+1==i)) == true
    end
    @shouldtestset2 "worki" begin
        a = zeros(Int,3)
        worki(a,(x,i)->a[i]=2*i)
        @test a  ==  [2,4,6]
    end
    @shouldtestset2 "map2" begin
        @test map2(1:3, 10:12, (+))  ==  [11,13,15]
    end
    @shouldtestset2 "mapmap" begin
        @test mapmap([[1 2]; [3 4]], x -> @p plus x 1)  ==  [[2 3]; [4 5]]
    end
    @shouldtestset2 "map!" begin
        f(x) = x*2
        f!(x) = x[:] = f(x)
        f!r(x) = f(x)
        f2!(r,x) = r[:] = vcat(f(x),f(x))
        a = [1 2 3; 4 5 6]
        @test map(a,f) == [2 4 6; 8 10 12]
        a = [1 2 3; 4 5 6]
        map!(a,f!)
        @test a == [2 4 6; 8 10 12]
        a = [1 2 3; 4 5 6]
        map!r(a,f)
        @test a == [2 4 6; 8 10 12]
        a = [1 2 3; 4 5 6]
        r = zeros(Int, 4, 3)
        map2!(a, r, f2!)
        @test r == 2*vcat(a,a)
        r = zeros(Int, 4, 3)
        r = map2!(a, x->vcat(x,x)*2, f2!)
        @test r == 2*vcat(a,a)
    end
    @shouldtestset2 "shmap" begin
        a = row(collect(1:3))
        r = shmap(a, x->@p plus x 1)
        @test r == @p plus a 1
        a = rand(10,round(Int,1e3))
        r = @p shmap a plus 1
        @test r == @p plus a 1
    end
    @shouldtestset2 "shmap!" begin
        a = share(row(collect(1:3)))
        orig = copy(a)
        shmap!(a, x->x[:] = @p plus x 1)
        @test a == @p plus orig 1
        a = share(rand(10,round(Int,1e3)))
        orig = copy(a)
        shmap!(a, x->x[:] = @p plus x 1)
        @test a == @p plus orig 1
    end
    @shouldtestset2 "shmap!r" begin
        a = share(row(collect(1:3)))
        orig = copy(a)
        shmap!r(a, x-> @p plus x 1)
        @test a == @p plus orig 1
        a = share(rand(10,round(Int,1e3)))
        orig = copy(a)
        shmap!r(a, x-> @p plus x 1)
        @test a == @p plus orig 1
    end
    # @shouldtestset2 "shmap2!" begin
    #     a = row(collect(1:3))
    #     r = shmap2!(a, x->x+1, (r,x)->r[:] = x+1)
    #     @test r == a + 1
    #     # r = shzerossiz(siz(a))
    #     # shmap2!(a, r, (r,x)->r[:] = x+1)
    #     # @test r == a + 1
    #     # a = rand(10,round(Int,1e3))
    #     # r = shmap2!(a, x->x+1, (r,x)->r[:] = x+1)
    #     # @test r == a + 1
    # end
    @shouldtestset2 "pmap" begin
        a = row(collect(1:3))
        r = FD.pmap(a, x->@p plus x 1)
        @test r == @p plus a 1
        @test eltype(r) == Int
        r = pmapvec(a, x->@p plus x 1)
        @test eltype(r) == Any
        a = rand(2,10)
        r = FD.pmap(a, x->@p plus x 1)
        @test r == @p plus a 1
    end
    @shouldtestset2 "lmap" begin
        a = row(collect(1:3))
        r = lmap(a, x->@p plus x 1)
        @test r == @p plus a 1
        @test eltype(r) == Int
        r = lmapvec(a, x->@p plus x 1)
        @test eltype(r) == Any
        a = rand(2,10)
        r = lmap(a, x->@p plus x 1)
        @test r == @p plus a 1
    end
    @shouldtestset2 "amap" begin
        a = row(1:30)
        r = amap(a, x->@p plus x 1)
        @test r == @p plus a 1
        a = rand(2,10)
        r = amap(a, x->@p plus x 1)
        @test r == @p plus a 1
        @test amap2(1:10, 1:10, +) == collect(2*(1:10))
        @test amap2("abc", 1:3, (x,y)->"$x$y") == ["a1","b2","c3"]
        # @test amapvec2(1:10, 1:10, +) == unstack(2*(1:10))
    end

    @shouldtestset2 "table" begin
        adder(x,y) = @p plus x y
        pass(x,y) = [x,y]
        passarray(x,y) = col([x,y])
        @test table(id,[1,2,3])  ==  [1,2,3]
        @test table([1,2,3],id)  ==  [1,2,3]
        @test table(pass,[1,2],1:3)  ==  cat([1 2; 1 1], [1 2; 2 2], [1 2; 3 3], dims=3)
        @test table([1,2],1:3,pass)  ==  cat([1 2; 1 1], [1 2; 2 2], [1 2; 3 3], dims=3)
        @test ltable(id,[1,2,3])  ==  [1,2,3]
        @test ltable([1,2,3],id)  ==  [1,2,3]
        @test ltable(pass,[1,2],1:3)  ==  cat([1 2; 1 1], [1 2; 2 2], [1 2; 3 3], dims=3)
        @test ltable([1,2],1:3,pass)  ==  cat([1 2; 1 1], [1 2; 2 2], [1 2; 3 3], dims=3)
        @test ptable(id,[1,2,3])  ==  [1,2,3]
        @test ptable([1,2,3],id)  ==  [1,2,3]
        @test ptable(pass,[1,2],1:3)  ==  cat([1 2; 1 1], [1 2; 2 2], [1 2; 3 3], dims=3)
        @test ptable([1,2],1:3,pass)  ==  cat([1 2; 1 1], [1 2; 2 2], [1 2; 3 3], dims=3)
        @test tableany(id,[1,2,3])  ==  Any[1,2,3]
        @test tableany([1,2,3],id)  ==  Any[1,2,3]
        @test tableany(pass,[1,2],1:3)  ==  reshape(Any[[1,1], [2,1], [1,2], [2,2], [1,3], [2,3]], 2, 3)
        @test tableany([1,2],1:3,pass)  ==  reshape(Any[[1,1], [2,1], [1,2], [2,2], [1,3], [2,3]], 2, 3)
        @test table(passarray,[1,2],1:3)  ==  cat([1 2; 1 1], [1 2; 2 2], [1 2; 3 3], dims=3)
        @test table([1,2],1:3,passarray)  ==  cat([1 2; 1 1], [1 2; 2 2], [1 2; 3 3], dims=3)
        @test tableany(passarray,[1,2],1:3)  ==  reshape(map(Any[[1,1], [2,1], [1,2], [2,2], [1,3], [2,3]],col), 2, 3)
        @test tableany([1,2],1:3,passarray)  ==  reshape(map(Any[[1,1], [2,1], [1,2], [2,2], [1,3], [2,3]],col), 2, 3)
        @test table(adder,[1 2; 3 4],1:3)  ==  cat([2 3; 4 5], [3 4; 5 6], [4 5; 6 7], dims=3)
        @test table([1 2; 3 4],1:3,adder)  ==  cat([2 3; 4 5], [3 4; 5 6], [4 5; 6 7], dims=3)
        # # @test size(ptableany((x,y)->myid(), 1:3, 1:4, nworkers = 2)) == (3,4) # FIXME
        # # @test size(ptableany(1:3, 1:4, (x,y)->myid(), nworkers = 2)) == (3,4) # FIXME
    end

    @shouldtestset2 "tee" begin
        a = Any[]
        @test tee(1:3, x->push!(a,@p plus x 1))  ==  1:3
        @test a  ==  Any[2:4]
        b = Any[]
        pushadd(x,param) = push!(b,@p plus x param)
        c = @p tee 1 pushadd 10
        @test b  ==  [11]
        @test c  ==  1
    end

    @shouldtestset2 "*" begin
        f(a) = abs.(a)
        @test (sum*f)([-1,0,1])  ==  2
        @test (join*split)("a b c")  ==  "abc"
        @test (last*join*split)("a b c")  ==  'c'
    end
    @shouldtestset2 "apply" begin
        f(a,b) = a+b
        g() = 1
        @test apply(f,1,2) == 3
        @test apply(g) == 1
    end
    @shouldtestset2 "minelem" begin
        d = [Dict(:a => 1), Dict(:a => 2), Dict(:a => 3)]
        @test minelem(d,x->at(x,:a)) == Dict(:a => 1)
        @test (@p minelem d at :a) == Dict(:a => 1)
        @test maxelem(d,x->at(x,:a)) == Dict(:a => 3)
        @test (@p maxelem d at :a) == Dict(:a => 3)
        @test extremaelem(d,x->at(x,:a)) == [Dict(:a => 1), Dict(:a => 3)]
        @test (@p extremaelem d at :a) == [Dict(:a => 1), Dict(:a => 3)]
        @test (@p map [10,11,12] x->@p minelem [10,0,12,13] y->(abs(y-x))) == [10,10,12]
    end
    @shouldtestset2 "isany" begin
        @test isany(zeros(3), x->x==0) == true
        @test areall(zeros(3), x->x==0) == true
        @test isany(zeros(3), x->x!=0) == false
        @test areall(zeros(3), x->x!=0) == false
        @test (@p zeros 3 | areall unequal 0) == false
        @test (@p zeros 3 | isany unequal 0) == false
    end
end

@shouldtestset "dataflow" begin
    @shouldtestset2 "unflatten" begin
        a = Any[[1],[2,3,4],[5,6]]
        @test unflatten(flatten(a,),a)  ==  a
    end
    @shouldtestset2 "reshape" begin
        @test size(reshape(rand(9)))  ==  (3,3)
    end
    @shouldtestset2 "rowcol" begin
        @test row(1)  ==  ones(Int, 1, 1)
        @test row([1,2,3])  ==  [1 2 3]
        @test row(1,2,3)    ==  [1 2 3]
        @test col(1)  ==  ones(Int, 1, 1)
        @test col([1,2,3])  ==  [1 2 3]'
        @test col(1,2,3)    ==  [1 2 3]'
    end
    @shouldtestset2 "stack" begin
        @test stack(Any[1,2]) == [1,2]
        @test stack(Any[[1 2],[3 4]]) == cat([1 2], [3 4], dims=3)
        @test stack(Any[zeros(2,3,4),ones(2,3,4)]) == cat(zeros(2,3,4),ones(2,3,4), dims=4)
    end
    @shouldtestset2 "flatten" begin
        @test flatten(Any[[1],[2]]) == [1,2]
        @test flatten(Any[row([1]),col([2])]) == [1 2]
        @test flatten(Any[[1 2],[2 3]]) == [1 2 2 3]
        @test flatten(Any[[1 2]',[2 3]']) == [1 2; 2 3]
        @test flatten(Any[[1, 2],[2, 3]]) == [1,2,2,3]
        @test flatten(Any[[1; 2],[2; 3]]) == [1,2,2,3]
        @test flatten(Any[Any[[1; 2],[2; 3]]]) == Any[[1; 2],[2; 3]]
        @test flatten(Char['a','b','c']) == "abc"
        @test flatten(Char['a' 'b' 'c']) == "abc"
        @test flatten(["a","b","c"]) == "abc"
        @test flatten(["a" "b" "c"]) == "abc"
        @test flatten(Any["a","b","c"]) == "abc"
        @test flatten(Any["a" "b" "c"]) == "abc"
    end
    @shouldtestset2 "concat" begin
        @test concat([1,2]) == [1,2]
        @test concat([[1,2];]) == [1,2]
        @test concat([[1,2];3]) == [1,2,3]
        @test concat(ones(2,3),zeros(2,4)) == hcat(ones(2,3),zeros(2,4))
    end
    @shouldtestset2 "unstack" begin
        @test unstack(cat([1 2],[2 3],dims=3)) == Any[[1 2],[2 3]]
        @test unstack(stack(Any[[1 2],[2 3]])) == Any[[1 2],[2 3]]
        @test unstack(stack(Any[zeros(2,3,4),ones(2,3,4)])) == Any[zeros(2,3,4),ones(2,3,4)]
        @test unstack([1 2 3; 4 5 6]) == Any[col([1,4]), col([2,5]), col([3,6])]
        @test unstack((1,2,3)) == Any[1,2,3]
    end
    @shouldtestset2 "riffle" begin
        @test riffle([1,2,3],0) == [1,0,2,0,3]
        @test riffle(1,0) == 1
        @test riffle([1 2 3; 4 5 6],zeros(2,1)) == [1 0 2 0 3; 4 0 5 0 6]
        @test riffle([1 2 3; 4 5 6],[8;9]) == [1 8 2 8 3; 4 9 5 9 6]
        @test riffle("abc",'_') == "a_b_c"
        @test riffle("abc","_") == "a_b_c"
        @test riffle("abc",", ") == "a, b, c"
        @test riffle([1,2,3],0) == [1,0,2,0,3]
    end
    @shouldtestset2 "matrix" begin
        a = Any[ones(2,3), zeros(2,3)]
        @test size(matrix(a))  ==  (6,2)
        @test size(matrix(zeros(2,3,4))) == (6,4)
        @test unmatrix(matrix(a),a)  ==  a
    end
    @shouldtestset2 "lines" begin
        @test lines("line1\nline2\r\nline3") == ["line1","line2","line3"]
        @test unlines(lines("line1\nline2\r\nline3")) == "line1\nline2\nline3"
    end
    @shouldtestset2 "findsub" begin
        a = [0 1 -1; 1 0 0]
        @test findsub(a)  ==  [2 1 1; 1 2 3]
    end
    @shouldtestset2 "subtoind" begin
        @test subtoind([1 1]', rand(2,3)) == 1
        @test subtoind([2 3]', rand(2,3)) == 6
        @test subtoind([1 2]', rand(2,3)) == 3
        @test subtoind([1 1 1]', rand(2,3,4)) == 1
        @test subtoind([2 3 4]', rand(2,3,4)) == 24
        @test subtoind([1 1 2]', rand(2,3,4)) == 7
    end
    @shouldtestset2 "randsample" begin
        @test size(randsample(1:10,5))  ==  (5,)
        @test size(randsample(rand(2,10),20))  ==  (2,20)
        @test randsample("aaa",5)  ==  "aaaaa"
    end
    @shouldtestset2 "flip" begin
        @test flip([])  ==  []
        @test flip("abc")  ==  "cba"
        @test flip(1:10)  ==  10:-1:1
        b = [1,2,3]
        flip!(b)
        @test b == [3,2,1]
        @test flip(Pair(1,2))  ==  Pair(2,1)
        @test flip(Dict(1=>2,3=>4))  ==  Dict(2=>1, 4=>3)
    end
    @shouldtestset2 "flipdims" begin
        @test size(flipdims(rand(2,3,4),1,1))  ==  (2,3,4)
        @test size(flipdims(rand(2,3,4),1,3))  ==  (4,3,2)
        @test size(flipdims(rand(2,3,4),2,1))  ==  (3,2,4)
    end
end

@shouldtestset "unzip" begin
    @test unzip([(1,1),(2,2)])  ==  ([1,2],[1,2])
    @test unzip([(1,2), "ab"])  ==  (Any[1,'a'], Any[2,'b'])
end

@shouldtestset "pipeline" begin
    @shouldtestset2 "general" begin
        add(x,y) = broadcast(+, x, y)
        minus(x,y) = broadcast(-, x ,y)

        x = @p add 1 2
        @test x == 3

        @test (@p add 1 2) == 3
        @test (@p add 1 2 | minus 2) == 1
        @test (@p add 1 2 | minus _ 2) == 1
        @test (@p add 1 2 | minus 3 _) == 0

        @test (@p map [1 2 3] add 1)  ==  [2 3 4]
        @test (@p map [1 2 3] minus 1)  ==  [0 1 2]

        x = @p id (1:5) | map add 1
        @test x  ==  [2,3,4,5,6]

        x = @p add (1:5) 1 | map add 1 | map minus 1
        @test x  ==  [2,3,4,5,6]

        x = @p map (1:5) add 1
        @test x  ==  [2,3,4,5,6]

        x = @p id [1] | map _ (x->@p plus x _ | plus _ | plus _ )
        @test x  ==  row([4])

        @test square(2)  == 4
        @test power(2,3)  == 8
    end

    @shouldtestset2 "map2" begin
        add2(a,b) = a+b
        x = @p map2 1:3 10:12 add2
        @test x  ==  [11,13,15]

        o = ones(2,3)
        z = zeros(2,3)
        @test (@p map2 o z plus) == ones(2,3)
        @test (@p map3 o z z (a,b,c)->a+b+c) == ones(2,3)
        @test (@p map4 o z z z (a,b,c,d)->a+b+c+d) == ones(2,3)
        @test (@p map5 o z z z z (a,b,c,d,e)->a+b+c+d+e) == ones(2,3)

        @test (@p mapvec2 (1:2) [3,4] (a,b)->"$a$b") == ["13","24"]
        @test (@p map2 (1:2) [3,4] (a,b)->"$a$b") == "1324"

        Z = ones(Int,3)
        add3(a,b,c) = a+b+c
        x = @p map3 1:3 10:12 100Z add3
        @test x  ==  [111,113,115]

        add4(a,b,c,d) = a+b+c+d
        x = @p map4 1:3 10:12 100Z 2000Z add4
        @test x  ==  [2111,2113,2115]

        add5(a,b,c,d,e) = a+b+c+d+e
        x = @p map5 1:3 10:12 100Z 2000Z 30000Z add5
        @test x  ==  [32111,32113,32115]
    end
end

@shouldtestset "io" begin
    @shouldtestset2 "readwrite" begin
        filename = tempname()
        write("line1\nline2\nline3",filename)
        @test read(filename, String)  ==  "line1\nline2\nline3"
        @test lines(read(filename, String))  ==  lines("line1\nline2\nline3")

        @p read filename String | lines
        @test (@p read filename String | lines | unlines | lines | unlines)  ==  "line1\nline2\nline3"
    end

    @shouldtestset2 "filenames" begin
        d = mktempdir()
        mk(a) = mkpath(joinpath(d,a))
        t(a...) = touch(joinpath(d,a...))
        mk("adir")
        mk("bdir")
        t("a")
        t("b")
        t("adir","a")
        t("adir","b")
        @test filenames(d)  ==  ["a","b"]
        @test dirnames(d)  ==  ["adir","bdir"]
        rm(d, recursive = true)
    end
end

@shouldtestset "@dict" begin
    a = 1
    b = 2
    @test @dict(a,b) == Dict(:a => 1, :b => 2)
end

println("done!")


text:
using DataDeps

register(DataDep("SemEval 2007t7",
    """
    Website: http://nlp.cs.swarthmore.edu/semeval/tasks/task07/description.shtml
    Data Website: http://nlp.cs.swarthmore.edu/semeval/tasks/task07/data.shtml
    Author: Roberto Navigli and Ken Litkowski

    The initial results and the task details are reported in:
    Navigli, R., Litkowski, K.C. and Hargraves, O., 2007, June. Semeval-2007 task 07: Coarse-grained english all-words task.
    _In Proceedings of the 4th International Workshop on Semantic Evaluations_ (pp. 30-35). Association for Computational Linguistics.
    Paper Website: http://anthology.aclweb.org/S/S07/S07-1.pdf#page=58
    """,
    "http://nlp.cs.swarthmore.edu/semeval/tasks/task07/data/".* ["trial", "test", "key"] .* ".tar.gz",
    "e0c1dc0d1644c019e28d36cacc837c5fd8c2a87bdafd34a7e71fa95a8b661dc7"
    ;
    post_fetch_method = unpack
))


text:
@testset "random" begin
    @testset "MersenneTwister" begin
        @testset "no args" begin
            rng, dΩ = frule((5.0,), MersenneTwister)
            @test rng isa MersenneTwister
            @test dΩ isa Zero

            rng, pb = rrule(MersenneTwister)
            @test rng isa MersenneTwister
            @test first(pb(10)) isa Zero
        end
        @testset "unary" begin
            rng, dΩ = frule((5.0, 4.0), MersenneTwister, 123)
            @test rng isa MersenneTwister
            @test dΩ isa Zero

            rng, pb = rrule(MersenneTwister, 123)
            @test rng isa MersenneTwister
            @test all(map(x -> x isa Zero, pb(10)))
        end
    end
end


text:
# save senario data
tire_model_data = DataFrame(ID = 1,tire_model=tire_model);
nonlinear_acceleration_constraints_data = DataFrame(ID = 1,nonlinear_acceleration_constraints=nonlinear_acceleration_constraints);
vertical_tire_force_constraints_data = DataFrame(ID = 1,vertical_tire_force_constraints=vertical_tire_force_constraints);
N_data = DataFrame(ID = 1,N =N );
execution_horizon_data = DataFrame(ID = 1,execution_horizon=execution_horizon);
solver_def_data = DataFrame(ID = 1, solver_def=solver_def[RR]);
integration_scheme_data = DataFrame(ID=1,integration_scheme=integration_scheme)
x_ref_data = DataFrame(ID=1, x_ref = x_ref)
y_ref_data = DataFrame(ID=1, y_ref = y_ref)
psi_ref_data = DataFrame(ID=1, psi_ref = psi_ref)

s_data = join(tire_model_data,nonlinear_acceleration_constraints_data,on=:ID);
s_data = join(s_data,vertical_tire_force_constraints_data,on=:ID);
s_data = join(s_data,N_data,on=:ID);
s_data = join(s_data,execution_horizon_data,on=:ID);
s_data = join(s_data,solver_def_data,on=:ID)
s_data = join(s_data,integration_scheme_data,on=:ID)
s_data = join(s_data,x_ref_data,on=:ID)
s_data = join(s_data,y_ref_data,on=:ID)
s_data = join(s_data,psi_ref_data,on=:ID)

if obstacle_exists == "true";
  A_data = DataFrame(ID = 1:Q, A = A);
  B_data = DataFrame(ID = 1:Q, B = B);
  s_x_data = DataFrame(ID = 1:Q, s_x = s_x);
  s_y_data = DataFrame(ID = 1:Q, s_y = s_y);
  X0_data = DataFrame(ID = 1:Q, X0 = X0);
  Y0_data = DataFrame(ID = 1:Q, Y0 = Y0);

  # build a single table
  obs_data = join(A_data,B_data, on = :ID);
  obs_data = join(obs_data,s_x_data,on =:ID);
  obs_data = join(obs_data,s_y_data,on =:ID);
  obs_data = join(obs_data,X0_data,on =:ID);
  obs_data = join(obs_data,Y0_data,on=:ID);
end


text:
const font_dir = "resources/fonts"

const font_array = [
         "Cascadia Mono" => "Cascadia/ttf/CascadiaMono.ttf"
         "Consolas" => "Consolas-Regular.ttf"
         "Cousine" => "noto-fonts-20201206-phase3/unhinted/ttf/Cousine/Cousine-Regular.ttf"
         "CMU Typewriter Text" => "cm-unicode-0.6.3a/cmuntt.otf"
         "DejaVu Sans Mono" => "dejavu-fonts-ttf-2.37/ttf/DejaVuSansMono.ttf"
         "Envy Code R" => "Envy Code R PR7/Envy Code R.ttf"
         "Everson Mono" => "evermono-7.0.0/Everson Mono.ttf"
         "FiraCode" => "FiraCode/ttf/FiraCode-Regular.ttf"
         # "FiraCode Retina" => "FiraCode/ttf/FiraCode-Retina.ttf"
         "FreeMono" => "FreeMono.otf"
         "Go Mono" => "Go-Mono.ttf"
         "Hack" => "Hack/ttf/Hack-Regular.ttf"
         "Inconsolata" => "Inconsolata/Inconsolata-Regular.otf"
         "Iosevka" => "iosevka/iosevka-regular.ttf"
         "JetBrains Mono" => "JetBrainsMono/ttf/JetBrainsMono-Regular.ttf"
         "JuliaMono" => "JuliaMono/JuliaMono-Regular.ttf"
         "Latin Modern Mono" => "latin-modern/lmmono10-regular.otf"
         "Liberation Mono" => "liberation-fonts-ttf-2.1.5/LiberationMono-Regular.ttf"
         "Menlo" => "Menlo.ttc"
         "Mononoki" => "mononoki/webfont/mononoki-Regular.ttf"
         #"Monaco" => "Monaco.dfont"
         # "Cousine hinted" => "noto-fonts-20201206-phase3/hinted/ttf/Cousine/Cousine-Regular.ttf"
         # "Noto Sans Mono hinted" => "noto-fonts-20201206-phase3/hinted/ttf/NotoSansMono/NotoSansMono-Regular.ttf"
         "Noto Sans Mono" => "noto-fonts-20201206-phase3/unhinted/ttf/NotoSansMono/NotoSansMono-Regular.ttf"
         "Roboto Mono" => "RobotoMono/fonts/ttf/RobotoMono-Regular.ttf"
         "SF Mono" => "sfmono/SFMono-Regular.otf"
         "Source Code Pro" => "SourceCodePro/SourceCodePro-Regular.ttf"
         "Ubuntu Mono" => "ubuntu-font-family-0.83/UbuntuMono-R.ttf"
        ]

const fonts = DataFrame(name=first.(font_array), path=joinpath.(font_dir, last.(font_array)))

max_stars_repo_name: waldyrious/mono-math

max_issues_repo_name: waldyrious/mono-math

max_forks_repo_name: waldyrious/mono-math


text:
@testset "test_synthesis" begin
P = tf(1.,[1.,1])
C = tf([1.,1],[1.,0])
L = P*C
Lsys = ss(L)

B = [1]
A = [1,1]
R = [1,1]
S = [1]
T = [1]

@test isapprox(minreal(feedback(P,C),1e-5), tf([1,0],[1,2,1]), rtol = 1e-5)
@test isapprox(numpoly(minreal(feedback(L),1e-5))[1].a, numpoly(tf(1,[1,1]))[1].a)# This test is ugly, but numerical stability is poor for minreal
@test feedback2dof(B,A,R,S,T) == tf(B.*T, conv(A,R) + [0;0;conv(B,S)])
@test feedback2dof(P,R,S,T) == tf(B.*T, conv(A,R) + [0;0;conv(B,S)])
@test isapprox(pole(minreal(tf(feedback(Lsys)),1e-5)) , pole(minreal(feedback(L),1e-5)), atol=1e-5)

Pint = tf(1,[1,1])
Cint = tf([1,1],[1,0])
Lint = P*C

@test isapprox(minreal(feedback(Pint,Cint),1e-5), tf([1,0],[1,2,1]), rtol = 1e-5) # TODO consider keeping minreal of Int system Int
@test isapprox(numpoly(minreal(feedback(Lint),1e-5))[1].a, numpoly(tf(1,[1,1]))[1].a)# This test is ugly, but numerical stability is poor for minreal
@test isapprox(pole(minreal(tf(feedback(Lsys)),1e-5)) , pole(minreal(feedback(L),1e-5)), atol=1e-5)

@test_throws ErrorException feedback(ss(1),ss(1))
@test_throws ErrorException feedback(ss([1 0; 0 1], ones(2,2), ones(1,2),0))
end


text:
#=
# A coefficient to be used in the weak form.
# Can be a number or a generated function.
# Values are in an array to allow vector/tensor valued coefficients
=#

struct Coefficient
    symbol::Symbol          # symbol used in expressions referring to this coefficient
    symvar::Array{Basic,1}  # Array of symbolic layer symbols(Basic symbols)
    index::Int              # index in the Femshop list of coefficients
    type::String            # constants for SCALAR, VECTOR, etc.
    location::String        # constant for NODAL, MODAL, CELL
    value::Array            # An array of either constant values(numbers) or genfunctions
end


text:
function sidebar(session::Session, names::NamedTuple, colors::NamedTuple; port::Int = 3141)

    ############################################################# sortable legend
    Legend = DOM.div( id = "legend", class = "legend", map( group ->
                DOM.ul( id = group, DOM.h2( class = "legend-header", selected=true, uppercasefirst(group),

                    ############################################# de/select all in group
                    onclick = js"""
                        var element = document.getElementById($group)
                        var selected = element.querySelector("h2").getAttribute('selected') == 'true' ? 'false' : 'true'
                        Array.from(element.children).forEach( x => x.setAttribute('selected',selected) )

                        fetch( 'http://localhost:$port/selection', {

                            headers: { 'Content-Type': 'application/json' },
                            method: 'POST',

                            body: JSON.stringify({
                                selected: selected == 'true' ? true : false,
                                name: $group
                            })

                        }).then( response => {
                            document.getElementById('map').tiles.refresh()

                        }).catch( error => {
                            console.error('Error:',error)
                        })

                    """
                )),
            ["populations","conditions","groups"]
        )
    )

    JSServe.onload( session, Legend, js"""
        function (container){

            ////////////////////////////////////////////// populate legend with groups and event listeners
            var colors = $(collect(values(colors.labels.names)))
            for ( const [key,value] of Object.entries($([names.populations;names.conditions;names.groups])) ) {

                var group = document.createElement('li')
                group.setAttribute('id',value)

                /////////////////////////////////////////////////// selection event
                group.setAttribute('selected',true)
                group.onclick = function (event) {
                    if (event.target.tagName != 'INPUT') {

                        var element = document.getElementById(value)
                        element.getAttribute('selected') == 'true' ? element.setAttribute('selected','false') : element.setAttribute('selected','true')
                        fetch( 'http://localhost:$port/selection', {

                            headers: { 'Content-Type': 'application/json' },
                            method: 'POST',

                            body: JSON.stringify({
                                selected: element.getAttribute('selected') == 'true' ? true : false,
                                name: value
                            })

                        }).then( response => {
                            document.getElementById('map').tiles.refresh()

                        }).catch( error => {
                            console.error('Error:',error)
                        })
                    }
                }

                var label = document.createElement('label')
                label.innerHTML = value

                var color = document.createElement('input')
                Object.assign( color, {

                    value: key < $(length(names.populations)) ? colors[key] : '#663F46',
                    type: 'color',

                    ////////////////////////////////////////////// marker color event
                    onchange: function (event) {
                        fetch( 'http://localhost:$port/colors', {

                            headers: { 'Content-Type': 'application/json' },
                            method: 'POST',

                            body: JSON.stringify({
                                color: event.target.value,
                                name: value
                            })

                        }).then( response => {
                            document.getElementById('map').tiles.refresh()

                        }).catch( error => {
                            console.error('Error:',error)
                        })
                    }
                })

                group.appendChild(color)
                group.appendChild(label)

                if ( key < $(length(names.populations)) )
                    document.getElementById('populations').appendChild(group)

                else if ( value.match(/\d+/g) != null)
                    document.getElementById('groups').appendChild(group)

                else
                    document.getElementById('conditions').appendChild(group)
            }

            //////////////////////////////////////////////////// legend groups as sortable lists
            ['populations','conditions','groups'].map( group => {

                Sortable.create( document.getElementById(group), {
                    group: group == 'populations' ? 'populations' : 'shared',

                    dataIdAttr: 'id',
                    animation: 150,

                    /////////////////////////////////////////// re-allocation of groups event
                    onAdd: function (event) {
                        fetch( 'http://localhost:$port/selection', {

                            headers: { 'Content-Type': 'application/json' },
                            method: 'POST',

                            body: JSON.stringify({
                                name: {
                                    'populations': Array.from(document.getElementById('populations').querySelectorAll('li')).map(x=>x.id),
                                    'conditions': Array.from(document.getElementById('conditions').querySelectorAll('li')).map(x=>x.id),
                                    'groups': Array.from(document.getElementById('groups').querySelectorAll('li')).map(x=>x.id)
                                }
                            })

                        }).then( response => {
                            document.getElementById('map').tiles.refresh()

                        }).catch( error => {
                            console.error('Error:',error)
                        })
                    }
                })
            })
        }
    """)

    ############################################################# violins
    Violins = DOM.div(id = "violins", class = "svg-container")
    JSServe.onload( session, Violins, js"""
        function (container){

            var svg = $d3.select("div#violins").append("svg")
                .attr("preserveAspectRatio", "xMinYMin meet")

                .attr("viewBox", "0 0 300 $(30*length(names.channels))")
                .classed("svg-content", true)
        }
    """)

    ############################################################# boxplots
    Boxplots = DOM.div(id = "boxplots", class = "svg-container")
    JSServe.onload( session, Boxplots, js"""
        function (container){

            var svg = $d3.select("div#boxplots").append("svg")
                .attr("preserveAspectRatio", "xMinYMin meet")

                .attr("viewBox", "0 0 300 $(300*length(names.populations))")
                .classed("svg-content", true)
        }
    """)

    return DOM.div( id = "sidebar", class = "sidebar collapsed",

        ######################################## sidebar layout
        DOM.div(class = "sidebar-tabs",
            DOM.ul(role = "tablist", map( (href, class) ->
                HTML("""

"""),
                ["annotations","expression","frequency"], ["fab fa-amilia","fa fa-chart-area","fa fa-chart-pie"]
            )),

            DOM.ul(role = "tablist", map( (href, class) ->
                HTML("""

"""),
                ["settings"], ["fa fa-cog"]
            )),
        ),

        ######################################## sidebar widgets
        DOM.div(class = "sidebar-content",

            DOM.div(class = "sidebar-pane",id = "annotations",
                HTML("""
Annotations
"""),
                DOM.div( id = "channel-selector", class="option-group",

                    "Colour by",
                    DOM.select( DOM.option.(["Labels";names.channels]), id="channel", onchange = js"""
                        var channel = document.getElementById('channel').value
                        var channelRange = $(colors.channels.range)

                        document.querySelector('svg.colorbar') ? document.querySelector('svg.colorbar').remove() : null
                        if (channel != 'Labels'){

                            var colorScale = $d3.scaleLinear().domain(channelRange[channel]).range($(colors.channels.hex))
                            $d3.select("#map").call( colorbar( colorScale, height=300, width=20, origin={x:40,y:10} ))
                        }

                        document.getElementById("map").tiles.refresh()
                    """)
                ),

                Legend
            ),

            DOM.div(class = "sidebar-pane",id = "expression",
                HTML("""
Expression
"""),

                HTML("""
 <button id="js-remove">Remove</button>
"""),
                DOM.div( id="polygon-interactions", class="option-group",

                    DOM.button( id="pan", type="button", class="primary", "Pan"),
                    DOM.button( id="polygon", type="button", class="success", "Polygon"),
                    DOM.button( id="modify", type="button", class="primary", style="visibility: hidden", "Modify"),
                    DOM.button( id="delete", type="button", class="danger", "Delete"),

                    DOM.button( id="save-boxplots", type="button", "Save",
                        onclick=js"""

                            var script = document.createElement('script');
                            Object.assign( script, { type: 'text/javascript', src: $FileSaver })
                            document.body.appendChild(script)

                            var svg = document.querySelector("#violins svg").innerHTML
                            var head = '<svg title="violins" version="1.1" xmlns="http://www.w3.org/2000/svg">'

                            var blob = new Blob([head+svg+"</svg>"],{type:"image/svg+xml"})
                            saveAs(blob,"violins.svg")
                    """)
                ),
                Violins
            ),

            DOM.div(class = "sidebar-pane",id = "frequency",
                HTML("""
Frequency
"""),
                DOM.div( id = "frequency-options", class="option-group",

                    DOM.button( id="frequency-calculate", type="button", "Calculate",
                        onclick=js"""

                            fetch( 'http://localhost:$port/count', {
                                method: 'GET'

                            //////////////////////////////////////////// update stats
                            }).then( response => response.json() ).then( data => {

                                var populations = Array.from(document.getElementById('populations').querySelectorAll('li')).filter(x=>x.getAttribute('selected')=='true')
                                var conditions = Array.from(document.getElementById('conditions').querySelectorAll('li')).filter(x=>x.getAttribute('selected')=='true')
                                var groups = Array.from(document.getElementById('groups').querySelectorAll('li')).filter(x=>x.getAttribute('selected')=='true')

                                boxplots( data,

                                    new Set(populations.map(x=>x.id)),
                                    new Set(conditions.map(x=>x.id)),
                                    new Set(groups.map(x=>x.id)),

                                    barcolors = populations.length > 0 ? Object.assign( ...populations.map( x => ({[x.id]: x.querySelector('input').value}) )) : {},
                                    markercolors = groups.length > 0 ? Object.assign( ...groups.map( x => ({[x.id]: x.querySelector('input').value}) )) : {}
                                )

                            }).catch( error => {
                                console.error('Error:',error)
                            })
                        """
                    ),

                    DOM.button( id="save-boxplots", type="button", "Save",
                        onclick=js"""

                            var script = document.createElement('script');
                            Object.assign( script, { type: 'text/javascript', src: $FileSaver })
                            document.body.appendChild(script)

                            var svg = document.querySelector("#boxplots svg").innerHTML
                            var head = '<svg title="boxplots" version="1.1" xmlns="http://www.w3.org/2000/svg">'

                            var blob = new Blob([head+svg+"</svg>"],{type:"image/svg+xml"})
                            saveAs(blob,"boxplots.svg")
                    """)
                ),
                Boxplots
            ),

            DOM.div(class = "sidebar-pane",id = "settings",
                HTML("""
Settings
"""),

                HTML("""
Marker Size
"""),
                DOM.input( type="range", min="0.01", step="0.01", max="5", value="1", class="slider", id="scale", onchange = js"""
                    document.getElementById("map").tiles.refresh()
                """)
            )
        )
    )
end

max_stars_repo_name: gszep/flow-explorer

max_issues_repo_name: gszep/flow-explorer

max_forks_repo_name: gszep/flow-explorer


text:
"""
ftanx()

Function and derivative for Figures 1.1 and 1.3 in the print book.
Also used as simple test problems.
"""
function ftanx(x)
    return tan(x) - x
end

function ftanxp(x)
    return sec(x)^2 - 1
end


text:
using Test, Parameters, BenchmarkTools

using FourierGPE

import FourierGPE:V
# ==== Units: ========================
# Units of ξ for length, 1/μ for time
# related by μ ≡ ħ²/mξ² = mc^2 where
# c = ħ/mξ is the speed of sound of
# the uniform system.

# ==== set simulation parameters ====
L = (16.,16.,16.)
N = (64,64,64)
γ = 0.05
tf = 4/γ
Nt = 200
t = LinRange(0.,tf,Nt)
# ========= Initialize simulation ======
X = xvecs(L,N)
x,y,z = X
y = y'
z = reshape(z,1,1,length(z))
V0 = @. zero(x*y*z)

sim = Sim(L,N)
# sim = Sim(sim,V0=StaticPotential(V0))

V(x,y,z,t) = 0.25*(x^2 + y^2 + z^2)*(1+0.01*sin(t))

@pack! sim = γ,tf,Nt,t
@unpack μ,g = sim

# ========= useful state functions

ψ0(x,y,z,μ,g) = sqrt(μ/g)*sqrt(max(1.0-V(x,y,z,0)/μ,0.0)+im*0.0)
healing(x,y,z,μ,g) = 1/sqrt(g*abs2(ψ0(x,y,z,μ,g)))

#make initial state
ψi = ψ0.(x,y,reshape(z,1,1,length(z)),μ,g)

dψi = similar(ψi)

ϕi = kspace(ψi,sim)
dϕi = similar(ϕi)
@pack! sim = ϕi,γ,tf,t

@time nlin!(dψi,ψi,sim,0.1)