text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: devops_guru
using AWS.Compat
using AWS.UUIDs

"""
    add_notification_channel(config)
    add_notification_channel(config, params::Dict{String,<:Any})

 Adds a notification channel to DevOps Guru. A notification channel is used to notify you
about important DevOps Guru events, such as when an insight is generated.  If you use an
Amazon SNS topic in another account, you must attach a policy to it that grants DevOps Guru
permission to it notifications. DevOps Guru adds the required policy on your behalf to send
notifications using Amazon SNS in your account. For more information, see Permissions for
cross account Amazon SNS topics. If you use an Amazon SNS topic that is encrypted by an AWS
Key Management Service customer-managed key (CMK), then you must add permissions to the
CMK. For more information, see Permissions for AWS KMS–encrypted Amazon SNS topics.

# Arguments
- `config`:  A NotificationChannelConfig object that specifies what type of notification
  channel to add. The one supported notification channel is Amazon Simple Notification
  Service (Amazon SNS).

"""
add_notification_channel(Config; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("PUT", "/channels", Dict{String, Any}("Config"=>Config); aws_config=aws_config)
add_notification_channel(Config, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("PUT", "/channels", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Config"=>Config), params)); aws_config=aws_config)

"""
    describe_account_health()
    describe_account_health(params::Dict{String,<:Any})

 Returns the number of open reactive insights, the number of open proactive insights, and
the number of metrics analyzed in your AWS account. Use these numbers to gauge the health
of operations in your AWS account.

"""
describe_account_health(; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/accounts/health"; aws_config=aws_config)
describe_account_health(params::AbstractDict{String, Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/accounts/health", params; aws_config=aws_config)

"""
    describe_account_overview(from_time)
    describe_account_overview(from_time, params::Dict{String,<:Any})

 For the time range passed in, returns the number of open reactive insight that were
created, the number of open proactive insights that were created, and the Mean Time to
Recover (MTTR) for all closed reactive insights.

# Arguments
- `from_time`:  The start of the time range passed in. The start time granularity is at the
  day level. The floor of the start time is used. Returned information occurred after this
  day.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ToTime"`:  The end of the time range passed in. The start time granularity is at the
  day level. The floor of the start time is used. Returned information occurred before this
  day. If this is not specified, then the current day is used.
"""
describe_account_overview(FromTime; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/accounts/overview", Dict{String, Any}("FromTime"=>FromTime); aws_config=aws_config)
describe_account_overview(FromTime, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/accounts/overview", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("FromTime"=>FromTime), params)); aws_config=aws_config)

"""
    describe_anomaly(id)
    describe_anomaly(id, params::Dict{String,<:Any})

 Returns details about an anomaly that you specify using its ID.

# Arguments
- `id`:  The ID of the anomaly.

"""
describe_anomaly(Id; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/anomalies/$(Id)"; aws_config=aws_config)
describe_anomaly(Id, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/anomalies/$(Id)", params; aws_config=aws_config)

"""
    describe_feedback()
    describe_feedback(params::Dict{String,<:Any})

 Returns the most recent feedback submitted in the current AWS account and Region.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"InsightId"`:  The ID of the insight for which the feedback was provided.
"""
describe_feedback(; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/feedback"; aws_config=aws_config)
describe_feedback(params::AbstractDict{String, Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/feedback", params; aws_config=aws_config)

"""
    describe_insight(id)
    describe_insight(id, params::Dict{String,<:Any})

 Returns details about an insight that you specify using its ID.

# Arguments
- `id`:  The ID of the insight.

"""
describe_insight(Id; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/insights/$(Id)"; aws_config=aws_config)
describe_insight(Id, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/insights/$(Id)", params; aws_config=aws_config)

"""
    describe_resource_collection_health(resource_collection_type)
    describe_resource_collection_health(resource_collection_type, params::Dict{String,<:Any})

 Returns the number of open proactive insights, open reactive insights, and the Mean Time
to Recover (MTTR) for all closed insights in resource collections in your account. You
specify the type of AWS resources collection. The one type of AWS resource collection
supported is AWS CloudFormation stacks. DevOps Guru can be configured to analyze only the
AWS resources that are defined in the stacks.

# Arguments
- `resource_collection_type`:  An AWS resource collection type. This type specifies how
  analyzed AWS resources are defined. The one type of AWS resource collection supported is
  AWS CloudFormation stacks. DevOps Guru can be configured to analyze only the AWS resources
  that are defined in the stacks.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"NextToken"`: The pagination token to use to retrieve the next page of results for this
  operation. If this value is null, it retrieves the first page.
"""
describe_resource_collection_health(ResourceCollectionType; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/accounts/health/resource-collection/$(ResourceCollectionType)"; aws_config=aws_config)
describe_resource_collection_health(ResourceCollectionType, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/accounts/health/resource-collection/$(ResourceCollectionType)", params; aws_config=aws_config)

"""
    describe_service_integration()
    describe_service_integration(params::Dict{String,<:Any})

 Returns the integration status of services that are integrated with DevOps Guru. The one
service that can be integrated with DevOps Guru is AWS Systems Manager, which can be used
to create an OpsItem for each generated insight.

"""
describe_service_integration(; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/service-integrations"; aws_config=aws_config)
describe_service_integration(params::AbstractDict{String, Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/service-integrations", params; aws_config=aws_config)

"""
    get_resource_collection(resource_collection_type)
    get_resource_collection(resource_collection_type, params::Dict{String,<:Any})

 Returns lists AWS resources that are of the specified resource collection type. The one
type of AWS resource collection supported is AWS CloudFormation stacks. DevOps Guru can be
configured to analyze only the AWS resources that are defined in the stacks.

# Arguments
- `resource_collection_type`:  The type of AWS resource collections to return. The one
  valid value is CLOUD_FORMATION for AWS CloudFormation stacks.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"NextToken"`: The pagination token to use to retrieve the next page of results for this
  operation. If this value is null, it retrieves the first page.
"""
get_resource_collection(ResourceCollectionType; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/resource-collections/$(ResourceCollectionType)"; aws_config=aws_config)
get_resource_collection(ResourceCollectionType, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("GET", "/resource-collections/$(ResourceCollectionType)", params; aws_config=aws_config)

"""
    list_anomalies_for_insight(insight_id)
    list_anomalies_for_insight(insight_id, params::Dict{String,<:Any})

 Returns a list of the anomalies that belong to an insight that you specify using its ID.

# Arguments
- `insight_id`:  The ID of the insight. The returned anomalies belong to this insight.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"NextToken"`: The pagination token to use to retrieve the next page of results for this
  operation. If this value is null, it retrieves the first page.
- `"StartTimeRange"`:  A time range used to specify when the requested anomalies started.
  All returned anomalies started during this time range.
"""
list_anomalies_for_insight(InsightId; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/anomalies/insight/$(InsightId)"; aws_config=aws_config)
list_anomalies_for_insight(InsightId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/anomalies/insight/$(InsightId)", params; aws_config=aws_config)

"""
    list_events(filters)
    list_events(filters, params::Dict{String,<:Any})

 Returns a list of the events emitted by the resources that are evaluated by DevOps Guru.
You can use filters to specify which events are returned.

# Arguments
- `filters`:  A ListEventsFilters object used to specify which events to return.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"NextToken"`: The pagination token to use to retrieve the next page of results for this
  operation. If this value is null, it retrieves the first page.
"""
list_events(Filters; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/events", Dict{String, Any}("Filters"=>Filters); aws_config=aws_config)
list_events(Filters, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/events", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Filters"=>Filters), params)); aws_config=aws_config)

"""
    list_insights(status_filter)
    list_insights(status_filter, params::Dict{String,<:Any})

 Returns a list of insights in your AWS account. You can specify which insights are
returned by their start time and status (ONGOING, CLOSED, or ANY).

# Arguments
- `status_filter`:  A filter used to filter the returned insights by their status. You can
  specify one status filter.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"NextToken"`: The pagination token to use to retrieve the next page of results for this
  operation. If this value is null, it retrieves the first page.
"""
list_insights(StatusFilter; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/insights", Dict{String, Any}("StatusFilter"=>StatusFilter); aws_config=aws_config)
list_insights(StatusFilter, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/insights", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("StatusFilter"=>StatusFilter), params)); aws_config=aws_config)

"""
    list_notification_channels()
    list_notification_channels(params::Dict{String,<:Any})

 Returns a list of notification channels configured for DevOps Guru. Each notification
channel is used to notify you when DevOps Guru generates an insight that contains
information about how to improve your operations. The one supported notification channel is
Amazon Simple Notification Service (Amazon SNS).

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"NextToken"`: The pagination token to use to retrieve the next page of results for this
  operation. If this value is null, it retrieves the first page.
"""
list_notification_channels(; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/channels"; aws_config=aws_config)
list_notification_channels(params::AbstractDict{String, Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/channels", params; aws_config=aws_config)

"""
    list_recommendations(insight_id)
    list_recommendations(insight_id, params::Dict{String,<:Any})

 Returns a list of a specified insight's recommendations. Each recommendation includes a
list of related metrics and a list of related events.

# Arguments
- `insight_id`:  The ID of the requested insight.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"NextToken"`: The pagination token to use to retrieve the next page of results for this
  operation. If this value is null, it retrieves the first page.
"""
list_recommendations(InsightId; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/recommendations", Dict{String, Any}("InsightId"=>InsightId); aws_config=aws_config)
list_recommendations(InsightId, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/recommendations", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("InsightId"=>InsightId), params)); aws_config=aws_config)

"""
    put_feedback()
    put_feedback(params::Dict{String,<:Any})

 Collects customer feedback about the specified insight.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"InsightFeedback"`:  The feedback from customers is about the recommendations in this
  insight.
"""
put_feedback(; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("PUT", "/feedback"; aws_config=aws_config)
put_feedback(params::AbstractDict{String, Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("PUT", "/feedback", params; aws_config=aws_config)

"""
    remove_notification_channel(id)
    remove_notification_channel(id, params::Dict{String,<:Any})

 Removes a notification channel from DevOps Guru. A notification channel is used to notify
you when DevOps Guru generates an insight that contains information about how to improve
your operations.

# Arguments
- `id`:  The ID of the notification channel to be removed.

"""
remove_notification_channel(Id; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("DELETE", "/channels/$(Id)"; aws_config=aws_config)
remove_notification_channel(Id, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("DELETE", "/channels/$(Id)", params; aws_config=aws_config)

"""
    search_insights(start_time_range, type)
    search_insights(start_time_range, type, params::Dict{String,<:Any})

 Returns a list of insights in your AWS account. You can specify which insights are
returned by their start time, one or more statuses (ONGOING, CLOSED, and CLOSED), one or
more severities (LOW, MEDIUM, and HIGH), and type (REACTIVE or PROACTIVE).   Use the
Filters parameter to specify status and severity search parameters. Use the Type parameter
to specify REACTIVE or PROACTIVE in your search.

# Arguments
- `start_time_range`:  The start of the time range passed in. Returned insights occurred
  after this time.
- `type`:  The type of insights you are searching for (REACTIVE or PROACTIVE).

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filters"`:  A SearchInsightsFilters object that is used to set the severity and status
  filters on your insight search.
- `"MaxResults"`: The maximum number of results to return with a single call. To retrieve
  the remaining results, make another call with the returned nextToken value.
- `"NextToken"`: The pagination token to use to retrieve the next page of results for this
  operation. If this value is null, it retrieves the first page.
"""
search_insights(StartTimeRange, Type; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/insights/search", Dict{String, Any}("StartTimeRange"=>StartTimeRange, "Type"=>Type); aws_config=aws_config)
search_insights(StartTimeRange, Type, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("POST", "/insights/search", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("StartTimeRange"=>StartTimeRange, "Type"=>Type), params)); aws_config=aws_config)

"""
    update_resource_collection(action, resource_collection)
    update_resource_collection(action, resource_collection, params::Dict{String,<:Any})

 Updates the collection of resources that DevOps Guru analyzes. The one type of AWS
resource collection supported is AWS CloudFormation stacks. DevOps Guru can be configured
to analyze only the AWS resources that are defined in the stacks. This method also creates
the IAM role required for you to use DevOps Guru.

# Arguments
- `action`:  Specifies if the resource collection in the request is added or deleted to the
  resource collection.
- `resource_collection`:

"""
update_resource_collection(Action, ResourceCollection; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("PUT", "/resource-collections", Dict{String, Any}("Action"=>Action, "ResourceCollection"=>ResourceCollection); aws_config=aws_config)
update_resource_collection(Action, ResourceCollection, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("PUT", "/resource-collections", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("Action"=>Action, "ResourceCollection"=>ResourceCollection), params)); aws_config=aws_config)

"""
    update_service_integration(service_integration)
    update_service_integration(service_integration, params::Dict{String,<:Any})

 Enables or disables integration with a service that can be integrated with DevOps Guru.
The one service that can be integrated with DevOps Guru is AWS Systems Manager, which can
be used to create an OpsItem for each generated insight.

# Arguments
- `service_integration`:  An IntegratedServiceConfig object used to specify the integrated
  service you want to update, and whether you want to update it to enabled or disabled.

"""
update_service_integration(ServiceIntegration; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("PUT", "/service-integrations", Dict{String, Any}("ServiceIntegration"=>ServiceIntegration); aws_config=aws_config)
update_service_integration(ServiceIntegration, params::AbstractDict{String, <:Any}; aws_config::AbstractAWSConfig=global_aws_config()) = devops_guru("PUT", "/service-integrations", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("ServiceIntegration"=>ServiceIntegration), params)); aws_config=aws_config)


text:
mark = ("S", "H", "C", "D")
marknum = Dict(zip(mark, 1:4))
nummark = Dict(zip(1:4, mark))
card = zeros(Bool, 4, 13)

n = parse(Int, readline())
for i in 1:n
    m, num = split(readline())
    num = parse(Int, num)
    card[marknum[m], num] = true
end

for i in 1:4
    for j in 1:13
        if !card[i, j]
            println(nummark[i], " ", j)
        end
    end
end

ext: jl


text:
import Base.Random: rand, srand
import RNG: AbstractRNG, gen_seed

"""
```julia
AbstractXorshift64 <: AbstractRNG{UInt64}
```

The base abstract type for `Xorshift64` and `Xorshift64Star`.
"""
abstract AbstractXorshift64 <: AbstractRNG{UInt64}

for star in (false, true)
    rng_name = Symbol(string("Xorshift64", star ? "Star" : ""))
    @eval begin
        type $rng_name <: AbstractXorshift64
            x::UInt64
            function $rng_name(seed::UInt64=gen_seed(UInt64))
                r = new(0)
                srand(r, seed)
                r
            end
        end

        $rng_name(seed::Integer) = $rng_name(seed % UInt64)

        @inline function xorshift_next(r::$rng_name)
            r.x $= r.x << 18
            r.x $= r.x >> 31
            r.x $= r.x << 11
            $(star ? :(r.x * 2685821657736338717) : :(r.x))
        end
    end
end

function srand(r::AbstractXorshift64, seed::Integer=gen_seed(UInt64))
    r.x = seed % UInt64
    xorshift_next(r)
    r
end

@inline rand(r::AbstractXorshift64, ::Type{UInt64}) = xorshift_next(r)


text:
function combine(obj::MelbourneWubbenaCombination, arg0::ObservationDataSet)
    return jcall(obj, "combine", CombinedObservationDataSet, (ObservationDataSet,), arg0)
end

function get_name(obj::MelbourneWubbenaCombination)
    return jcall(obj, "getName", JString, ())
end


text:
#=
    Thermal energy storage modelling
 =#

mutable struct ThermalStorage <: AbstractStorage
     # Paramètres
     α_p_ch::Float64
     α_p_dch::Float64
     η_ch::Float64
     η_dch::Float64
     η_self::Float64
     α_soc_min::Float64
     α_soc_max::Float64
     lifetime::Int64
     bounds::NamedTuple{(:lb, :ub), Tuple{Float64, Float64}}
     # Initial conditions
     Erated_ini::Float64
     soc_ini::Float64
     soh_ini::Float64
     # Variables
     Erated::AbstractArray{Float64,2}
     carrier::Heat
     soc::AbstractArray{Float64,3}
     # Eco
     cost::AbstractArray{Float64,2}
     # Inner constructor
     ThermalStorage(; α_p_ch = 1.5,
          α_p_dch = 1.5,
          η_ch = 0.8,
          η_dch = 0.8,
          η_self = 0.008,
          α_soc_min = 0.,
          α_soc_max = 1.,
          lifetime = 25,
          bounds = (lb = 0., ub = 1000.),
          Erated_ini = 1e-6,
          soc_ini = 0.5,
          soh_ini = 1.) =
          new(α_p_ch, α_p_dch, η_ch, η_dch, η_self, α_soc_min, α_soc_max, lifetime, bounds, Erated_ini, soc_ini, soh_ini)
end

### Preallocation
function preallocate!(tes::ThermalStorage, nh::Int64, ny::Int64, ns::Int64)
    tes.Erated = convert(SharedArray,zeros(ny+1, ns)) ; tes.Erated[1,:] .= tes.Erated_ini
    tes.carrier = Heat()
    tes.carrier.power = convert(SharedArray,zeros(nh, ny, ns))
    tes.soc = convert(SharedArray,zeros(nh+1, ny+1, ns)) ; tes.soc[1,1,:] .= tes.soc_ini
    tes.cost = convert(SharedArray,zeros(ny, ns))
    return tes
end

### Operation dynamic
function compute_operation_dynamics!(h::Int64, y::Int64, s::Int64, tes::ThermalStorage, decision::Float64, Δh::Int64)
     tes.soc[h+1,y,s], tes.carrier.power[h,y,s] = compute_operation_dynamics(tes, (Erated = tes.Erated[y,s], soc = tes.soc[h,y,s]), decision, Δh)
end

function compute_operation_dynamics(tes::ThermalStorage, state::NamedTuple{(:Erated, :soc), Tuple{Float64, Float64}}, decision::Float64, Δh::Int64)
     # Control power constraint and correction
     power_dch = max(min(decision, tes.α_p_dch * state.Erated, tes.η_dch * (state.soc * (1. - tes.η_self * Δh) - tes.α_soc_min) * state.Erated / Δh), 0.)
     power_ch = min(max(decision, -tes.α_p_ch * state.Erated, (state.soc * (1. - tes.η_self * Δh) - tes.α_soc_max) * state.Erated / Δh / tes.η_ch), 0.)
     # SoC dynamic
     soc_next = state.soc * (1. - tes.η_self * Δh) - (power_ch * tes.η_ch + power_dch / tes.η_dch) * Δh / state.Erated
     return soc_next, power_dch + power_ch
end

### Investment dynamic
function compute_investment_dynamics!(y::Int64, s::Int64, tes::ThermalStorage, decision::Union{Float64, Int64})
    tes.Erated[y+1,s], tes.soc[1,y+1,s] = compute_investment_dynamics(tes, (Erated = tes.Erated[y,s], soc = tes.soc[end,y,s]), decision)
end

function compute_investment_dynamics(tes::ThermalStorage, state::NamedTuple{(:Erated, :soc), Tuple{Float64, Float64}}, decision::Union{Float64, Int64})
    if decision > 1e-2
        Erated_next = decision
        soc_next = tes.soc_ini
    else
        Erated_next = state.Erated
        soc_next = state.soc
    end
    return Erated_next, soc_next
end


text:
function collatz(x)
    steps = 0
    while x != 1
        steps += 1
        if x % 2 == 0
            x = x / 2
        else
            x = (x * 3) + 1
        end
    end
    return steps
end
print("Collatz Conjecture of: ")
num = readline()
num = parse(Int64, num)
print(collatz(num))

max_stars_repo_name: ellygaytor/Projects

max_issues_repo_name: ellygaytor/Projects

max_forks_repo_name: ellygaytor/Projects


text:
mt = Random.MersenneTwister(42)
(µ, σ) = (5.0, 1.0)
xs = [rand(mt, Normal(µ, σ)) for _ in 1:50]

ndist = Normal(0.0, 0.3)
gkernel = KernelDensity.kde(xs, ndist)

tdist = TriangularDist(-0.5, 0.5)
tkernel = KernelDensity.kde(xs, tdist)

p = Plots.plot(tkernel.x, tkernel.density, labels = "Triangular kernel")
Plots.plot!(p, gkernel.x, gkernel.density,
            labels = "Gaussian kernel", legend = :left)
Plots.title!(p, "Comparison of Gaussian and triangular kernels")
Plots.savefig(joinpath(base_img, "triangle_kernel.pdf"))


text:
using MicrostructureNoise
using Test

include("microstructure.jl")
include("piecewise.jl")


text:
struct Cdouble6
    x1::Cdouble
    x2::Cdouble
    x3::Cdouble
    x4::Cdouble
    x5::Cdouble
    x6::Cdouble
end

struct Cdouble15
    x1::Cdouble
    x2::Cdouble
    x3::Cdouble
    x4::Cdouble
    x5::Cdouble
    x6::Cdouble
    x7::Cdouble
    x8::Cdouble
    x9::Cdouble
    x10::Cdouble
    x11::Cdouble
    x12::Cdouble
    x13::Cdouble
    x14::Cdouble
    x15::Cdouble
end

struct Cdouble21
    x1::Cdouble
    x2::Cdouble
    x3::Cdouble
    x4::Cdouble
    x5::Cdouble
    x6::Cdouble
    x7::Cdouble
    x8::Cdouble
    x9::Cdouble
    x10::Cdouble
    x11::Cdouble
    x12::Cdouble
    x13::Cdouble
    x14::Cdouble
    x15::Cdouble
    x16::Cdouble
    x17::Cdouble
    x18::Cdouble
    x19::Cdouble
    x20::Cdouble
    x21::Cdouble
end

mutable struct geod_geodesic <: _geodesic
    a::Cdouble
    f::Cdouble
    f1::Cdouble
    e2::Cdouble
    ep2::Cdouble
    n::Cdouble
    b::Cdouble
    c2::Cdouble
    etol2::Cdouble

    # Arrays of parameters must be expanded manually,
    # currently (either inline, or in an immutable helper-type)
    # In the future, some of these restrictions may be reduced/eliminated.
    A3x::Cdouble6
    C3x::Cdouble15
    C4x::Cdouble21

    geod_geodesic() = new()
end

"""
Construct an ellipsoid of revolution with

    equatorial radius a,
    flattening f,

Remark, we construct it when constructing a [Projection] using the formulas:

    f = (a − b)/a = 1 − sqrt(1-es)
    n = (a − b)/(a + b) = f /(2 − f)
    es = (a^2 − b^2)/a^2 = f(2 − f)

Reference: equations (1)-(3) of
    Algorithms for geodesics (arXiv:1109.4448v2 [physics.geo-ph] 28 Mar 2012)
"""
function geod_geodesic(a::Cdouble, f::Cdouble)
    geod = geod_geodesic()
    ccall((:geod_init, libproj), Cvoid, (Ptr{Cvoid},Cdouble,Cdouble),
          pointer_from_objref(geod), a, f)
    geod
end

"""
Solve the direct geodesic problem.

Args:

    g        - the geod_geodesic object specifying the ellipsoid.
    lonlat   - where lat ∈ [-90, 90], lon ∈ [-540, 540), modified in-place to [dest] (described below)
    azimuth  - azimuth (degrees) ∈ [-540, 540)
    distance - distance (metres) to move from (lon,lat); can be negative

Returns:

    dest     - destination after moving for [distance] metres in [azimuth] direction.
    azi      - forward azimuth (degrees) at destination [dest].

Remarks:

    If either point is at a pole, the azimuth is defined by keeping the longitude fixed,
    writing lat = 90 +/- eps, and taking the limit as eps -> 0+. An arc length greater than 180deg
    signifies a geodesic which is not a shortest path.
"""
function _geod_direct!(geod::geod_geodesic, lonlat::Vector{Cdouble}, azimuth::Cdouble, distance::Cdouble)
    p = pointer(lonlat)
    azi = Ref{Cdouble}() # the (forward) azimuth at the destination
    ccall((:geod_direct, libproj),Cvoid,(Ptr{Cvoid},Cdouble,Cdouble,Cdouble,Cdouble,Ptr{Cdouble},Ptr{Cdouble},
          Ptr{Cdouble}), pointer_from_objref(geod), lonlat[2], lonlat[1], azimuth, distance, p+sizeof(Cdouble), p, azi)
    lonlat, azi[]
end

"""
Solve the inverse geodesic problem.

Args:

    g       - the geod_geodesic object specifying the ellipsoid.
    lonlat1 - point 1 (degrees), where lat ∈ [-90, 90], lon ∈ [-540, 540)
    lonlat2 - point 2 (degrees), where lat ∈ [-90, 90], lon ∈ [-540, 540)

Returns:

    dist    - distance between point 1 and point 2 (meters).
    azi1    - azimuth at point 1 (degrees) ∈ [-180, 180)
    azi2    - (forward) azimuth at point 2 (degrees) ∈ [-180, 180)

Remarks:

    If either point is at a pole, the azimuth is defined by keeping the longitude fixed,
    writing lat = 90 +/- eps, and taking the limit as eps -> 0+.
"""
function _geod_inverse(geod::geod_geodesic, lonlat1::Vector{Cdouble}, lonlat2::Vector{Cdouble})
    dist = Ref{Cdouble}()
    azi1 = Ref{Cdouble}()
    azi2 = Ref{Cdouble}()
    ccall((:geod_inverse, libproj), Cvoid, (Ptr{Cvoid},Cdouble,Cdouble,Cdouble,
          Cdouble,Ptr{Cdouble},Ptr{Cdouble},Ptr{Cdouble}),
          pointer_from_objref(geod), lonlat1[2], lonlat1[1], lonlat2[2], lonlat2[1], dist, azi1, azi2)
    dist[], azi1[], azi2[]
end


text:
using Base.Test

using MarketData
using TimeSeries

using MarketTechnicals

@testset "Candlesticks" begin

@testset "doji" begin
    @test ohlc[find(doji(ohlc))].timestamp[1] == Date(2000, 5, 30)
    @test ohlc[find(doji(ohlc))].timestamp[2] == Date(2000, 12, 11)
    @test length(ohlc[find(doji(ohlc))])      == 5
end

end  # @testset "Candlesticks"


text:
using Distributions, Test

@testset "truncated uniform" begin
    # just test equivalence of truncation results
    u = Uniform(1, 2)
    @test truncated(u, -Inf, Inf) == u
    @test truncated(u, 0, Inf) == u
    @test truncated(u, -Inf, 2.1) == u
    @test truncated(u, 1.1, Inf) == Uniform(1.1, 2)
    @test truncated(u, 1.1, 2.1) == Uniform(1.1, 2)
    @test truncated(u, 1.1, 1.9) == Uniform(1.1, 1.9)
end


text:
import Base: show

abstract Missing

type HereSomewhere <: Missing
    val::Float64
    HereSomewhere(x) = isnan(x) ? new(x) : error("You're not really lost here are you?")
end

type Consumed <: Missing
    val::Float64
    Consumed(x) = isnan(x) ? new(x) : error("Value was actually generated afterall, your lucky day!")
end

type Nonsense <: Missing
    val::Float64
    Nonsense(x) = isnan(x) ? new(x) : error("This actually does make sense.")
end

type Shifted <: Missing
    val::Float64
    Shifted(x) = isnan(x) ? new(x) : error("No shift has occurred.")
end

function show(io::IO, u::HereSomewhere)
    println()
    println("Exists but is not known")
end

function show(io::IO, u::Consumed)
    println()
    println("Not enough previous data to generate a meaningful value")
end

function show(io::IO, u::Nonsense)
    println()
    println("Doesn't make sense in known universe")
end

function show(io::IO, u::Shifted)
    println()
    println("Doesn't make sense in known universe")
end


text:
# This file is a part of BAT.jl, licensed under the MIT License (MIT).
using BAT
using Test

using LinearAlgebra
using StatsBase, Distributions, StatsBase, ValueShapes

@testset "HamiltonianMC" begin
    rng = bat_rng()
    target = NamedTupleDist(a = Normal(1, 1.5), b = MvNormal([-1.0, 2.0], [2.0 1.5; 1.5 3.0]))

    density = @inferred(convert(AbstractDensity, target))
    @test density isa BAT.DistributionDensity

    algorithm = HamiltonianMC()
    nchains = 4

    @testset "MCMC iteration" begin
        v_init = bat_initval(rng, density, InitFromTarget()).result
        # Note: No @inferred, since MCMCIterator is not type stable (yet) with HamiltonianMC
        @test MCMCIterator(deepcopy(rng), algorithm, density, 1, unshaped(v_init, varshape(density))) isa BAT.AHMCIterator
        chain = MCMCIterator(deepcopy(rng), algorithm, density, 1, unshaped(v_init, varshape(density)))
        samples = DensitySampleVector(chain)
        BAT.mcmc_iterate!(samples, chain, max_nsteps = 10^5, nonzero_weights = false)
        @test chain.stepno == 10^5
        @test minimum(samples.weight) == 0
        @test isapprox(length(samples), 10^5, atol = 20)
        @test length(samples) == sum(samples.weight)
        @test isapprox(mean(samples), [1, -1, 2], atol = 0.2)
        @test isapprox(cov(samples), cov(unshaped(target)), atol = 0.3)

        samples = DensitySampleVector(chain)
        BAT.mcmc_iterate!(samples, chain, max_nsteps = 10^3, nonzero_weights = true)
        @test minimum(samples.weight) == 1
    end

    @testset "MCMC tuning and burn-in" begin
        init_alg = MCMCChainPoolInit()
        tuning_alg = MCMCNoOpTuning()
        burnin_alg = MCMCMultiCycleBurnin()
        convergence_test = BrooksGelmanConvergence()
        strict = true
        nonzero_weights = false
        callback = (x...) -> nothing
        max_nsteps = 10^5

        # Note: No @inferred, not type stable (yet) with HamiltonianMC
        init_result = BAT.mcmc_init!(
            rng,
            algorithm,
            density,
            nchains,
            init_alg,
            tuning_alg,
            nonzero_weights,
            callback,
        )

        (chains, tuners, outputs) = init_result
        @test chains isa AbstractVector{<:BAT.AHMCIterator}
        @test tuners isa AbstractVector{<:BAT.MCMCNoOpTuner}
        @test outputs isa AbstractVector{<:DensitySampleVector}

        BAT.mcmc_burnin!(
            outputs,
            tuners,
            chains,
            burnin_alg,
            convergence_test,
            strict,
            nonzero_weights,
            callback
        )

        BAT.mcmc_iterate!(
            outputs,
            chains;
            max_nsteps = div(max_nsteps, length(chains)),
            nonzero_weights = nonzero_weights,
            callback = callback
        )

        samples = DensitySampleVector(first(chains))
        append!.(Ref(samples), outputs)

        @test length(samples) == sum(samples.weight)
        @test isapprox(mean(samples), [1, -1, 2], atol = 0.3)
        @test isapprox(cov(samples), cov(unshaped(target)), atol = 0.4)
    end

    @testset "bat_sample" begin
        samples = bat_sample(
            density,
            MCMCSampling(
                mcalg = algorithm,
                trafo = NoDensityTransform(),
                nsteps = 10^4,
                store_burnin = true
            )
        ).result

        # ToDo: First HMC sample currently had chaincycle set to 0, should be fixed.
        # @test first(samples).info.chaincycle == 1
        @test samples[2].info.chaincycle == 1

        samples = bat_sample(
            density,
            MCMCSampling(
                mcalg = algorithm,
                trafo = NoDensityTransform(),
                nsteps = 10^4,
                store_burnin = false
            )
        ).result

        @test first(samples).info.chaincycle >= 2

        @test samples.v isa ShapedAsNTArray
        @test isapprox(mean(unshaped.(samples)), [1, -1, 2], atol = 0.3)
        @test isapprox(cov(unshaped.(samples)), cov(unshaped(target)), atol = 0.4)
    end
end


text:
module Circuits
using Latexify

export Circuit, @circuit
export Resistor, Inductor, Capacitor, Short, Open
export Series, Parallel
export Battery, VSource, SinusSource

export voltageDivision, currentDivision, simplify, -->
export latexstandalone

import Base: show, iterate, length, //

CircuitIndex = Union{Int64,Symbol}

abstract type AbstractComponent end
abstract type Impedor <: AbstractComponent end
abstract type Network <: Impedor end
abstract type Source <: AbstractComponent end
abstract type VoltageSource <: Source end
abstract type CurrentSource <: Source end

# Circuit {{{
struct Circuit # {{{
    coordinates::Dict#{CircuitIndex, Tuple{Float64, Float64}}
    connections::Dict#{Tuple{CircuitIndex, CircuitIndex}, <:AbstractComponent}
end # }}}

function show(io::IO, m::MIME"text/plain", x::Circuit) # {{{
    return print(
        io,
        "Circuit with ",
        length(x.coordinates),
        " nodes, ",
        count(isa.(values(x.connections), Impedor)),
        " impedors and ",
        count(isa.(values(x.connections), Source)),
        " sources.",
    )
end # }}}

function show(
    io::IO, m::MIME"text/circuitikz", x::Circuit; shownodes=false, expandnetworks=false
) # {{{
    print(io, "\\draw %\n")
    for (k, v) in x.connections
        printconnection(io, x.coordinates[k[1]], x.coordinates[k[2]], v; expandnetworks)
    end
    print(io, "\t; ")
    if shownodes
        print(io, "\\path[red, every node/.style={circle, draw=red, fill=white}]")
        for (i, c) in x.coordinates
            print(io, " (", join(c, ','), ") node {", i, "}")
        end
        print(io, "; \n")
    end
end # }}}
# }}}

# Circuit macro {{{
"""
```
<coordinate> <component> <coordinate> <component>...
```

Label coordinates by `name:(x, y)` to reuse later with `:name`.

```julia
@circuit begin
a:(0, 0) --> R(10) --> b:(1, 0) --> C(4) --> (2, 0)
:b --> R(10) --> c:(1, 1)
end
```
"""
macro circuit(args...)
    return esc(generate_circuit(args[1]))
end

function generate_circuit(arg::Expr)
    if arg.head !== :block
        expressions = (arg,)
    else
        expressions = arg.args
    end
    coordinates = Dict{CircuitIndex,Union{Expr,Symbol}}()
    components = Expr[]

    for e in expressions
        push_stuff!(e, coordinates, components)
    end
    return Expr(
        :call,
        :Circuit,
        Expr(
            :call,
            :Dict,
            Expr.(:call, :(=>), QuoteNode.(keys(coordinates)), values(coordinates))...,
        ),
        Expr(:call, :Dict, components...),
    )
end

"""
`push_stuff!(e, coord, comp)`

recursively add the contents of `e` to the coordinate list `coord` and/or the
component list `comp`. Returns the index if `e` represents a coordinate, a
`(component, index)` tuple if `e` represents a component, connected to
coordinate `index` to the right, or the index of the leftmost coordinate of a
chain starting and ending with a coordinate.
"""
function push_stuff! end

# This recursion is disgusting in every way. Luckily they will never grow very
# large (knock on wood)
function push_stuff!(e::Expr, coord, comp)
    (head, args) = (e.head, e.args)
    if head === :-->
        left = push_stuff!(args[1], coord, comp)
        right = push_stuff!(args[2], coord, comp)
        if isa(left, CircuitIndex) && isa(right, CircuitIndex)
            # coordinate --> coordinate
            push!(comp, :(($(QuoteNode(left)), $(QuoteNode(right))) => Short()))
            return left
        end
        if left isa CircuitIndex
            # coordinate --> component
            push!(
                comp,
                :(($(QuoteNode(left)), $(QuoteNode(right.index))) => $(right.component)),
            )
            return left
        end
        if right isa CircuitIndex
            # component --> coordinate
            # should be a (component, index) tuple...
            return (component=left, index=right)
        end
        # component --> component
        return (component=:(Series($left, $(right.component))), index=right.index)
    end
    if head === :call
        if args[1] === ://
            # component // component
            left = push_stuff!(args[1], coord, comp)
            right = push_stuff!(args[2], coord, comp)
            return :(Parallel($left, $right))
        end
        if args[1] === :(:)
            # Label coordinate arg[2]:arg[3] ( a:(1, 2) )
            push!(coord, args[2] => args[3])
            return args[2]
        end
        # Function call
        return e
    end
    if head === :tuple
        # Naked coordinate
        i = length(coord)
        push!(coord, i => e)
        return i
    end

    return error("I don't know what to do with argument $e")
end

function push_stuff!(e::QuoteNode, coord, comp)
    if !haskey(coord, e.value)
        error("Coordinate $(e.value) doesn't exist")
    end
    return e.value
end

function push_stuff!(e::Symbol, coord, comp)
    if !haskey(coord, e)
        error("Coordinate $e doesn't exist")
    end
    return e
end

push_stuff!(::LineNumberNode, args...) = nothing

# Circuit macro }}}

# Component macro {{{
macro component(args...)
    return esc(component_helper(args...))
end

function component_helper(type, name, circuitikzname, parameters...)

    #  Struct generation {{{
    structexpr = Expr(
        :struct,
        false,
        Expr(:<:, isempty(parameters) ? name : Expr(:curly, name, :(T <: Number)), type),
        Expr(:block, Expr.(:(::), parameters, :T)...),
    )
    #  }}}

    #  Show generation {{{
    showexpr = Expr(
        :function,
        Expr(:call, :show, :(io::IO), Expr(:(::), :x, name)),
        Expr(
            :block,
            Expr(:call, :print, :io, string(name)),
            if isempty(parameters)
                nothing
            else
                Expr(
                    :call, :print, :io, '(', Expr.(:., :x, QuoteNode.(parameters))..., ')'
                )
            end,
        ),
    )
    #  }}}

    #  Circuitikz generation {{{
    circuitikzexpr = Expr(
        :function,
        Expr(:call, :show, :(io::IO), :(::MIME"text/circuitikz"), Expr(:(::), :x, name)),
        Expr(
            :block,
            Expr(:call, :print, :io, string(circuitikzname)),
            if isempty(parameters)
                nothing
            else
                Expr(
                    :block,
                    :(print(io, '=')),
                    Expr(
                        :call,
                        :print,
                        :io,
                        Expr(:call, :latexify, Expr(:., :x, QuoteNode(first(parameters)))),
                    ),
                )
            end,
        ),
    )
    #  }}}

    return Expr(:block, structexpr, showexpr, circuitikzexpr)
end
# Component macro }}}

##= Generate components {{{
#           type                name        circuitikzname  parameters
@component Impedor Resistor R R
@component Impedor Capacitor C C
@component Impedor Inductor L L
@component Impedor Short short
@component Impedor Open open

@component VoltageSource Battery battery U
@component VoltageSource VSource battery1 U
@component VoltageSource SinusSource vsourcesin U ω
# }}}=#

# Network {{{
function Network(::Type{T}, args::Tuple{Vararg{<:Impedor}}) where {T<:Network}
    l = Impedor[]
    for x in args
        # Make sure a Series doesn't contain Series objects (because that would be very silly)
        unwind!(l, T, x)
    end
    isone(length(l)) && return l[1]
    return T(l)
end
# }}}

# Series {{{
struct Series <: Network
    l::Vector{<:Impedor}
end

Series(args::Vararg{<:Impedor}) = Network(Series, args)

# Show {{{
show(io::IO, x::Series) = join(io, x, " --> ")
show(io::IO, ::MIME"text/circuitikz", x::Series) = print(io, "generic={--}")
# Show }}}

# Iteration {{{
iterate(x::Series, state...) = iterate(x.l, state...)
Base.IteratorEltype(::Series) = Base.HasEltype()
eltype(x::Series) = eltype(x.l)
Base.IteratorSize(::Series) = Base.HasLength()
length(x::Series) = length(x.l)
# Iteration }}}

-->(a::Impedor, b::Impedor) = Series(a, b)
# Series }}}

# Parallel {{{
struct Parallel <: Network
    l::Vector{<:Impedor}
end

Parallel(args::Vararg{<:Impedor}) = Network(Parallel, args)

# Show {{{
function show(io::IO, x::Parallel)
    print(io, '(')
    join(io, x, ") // (")
    return print(io, ')')
end
show(io::IO, ::MIME"text/circuitikz", x::Parallel) = print(io, "generic={//}")
# Show }}}

# Iteration {{{
iterate(x::Parallel, state...) = iterate(x.l, state...)
Base.IteratorEltype(::Parallel) = Base.HasEltype()
eltype(x::Parallel) = eltype(x.l)
Base.IteratorSize(::Parallel) = Base.HasLength()
length(x::Parallel) = length(x.l)
# Iteration }}}

//(a::Impedor, b::Impedor) = Parallel(a, b)
# Parallel }}}

# Parameters of components {{{
impedance(x::Resistor, s=0) = x.R
impedance(x::Capacitor, s=0) = 1 / (s * x.C)
impedance(x::Inductor, s=0) = s * x.L
impedance(x::Short, s=0) = 0
impedance(x::Open, s=0) = Inf
impedance(x::Series, s=0) = sum(impedance.(x, s))
impedance(x::Parallel, s=0) = invsum(impedance.(x, s))

voltage(x::Battery, s=0) = x.U
voltage(x::VSource, s=0) = x.U
voltage(x::SinusSource, s=0) = x.U * x.ω / (s^2 + ω^2)
# Parameters of components }}}

# Voltage and current division {{{
"""
```julia
voltageDivision(component, s=0)
```
If a total voltage ``U`` is applied over `component`, the voltage over
respective sub-component is ``k·U``, where ``k`` is the coefficient returned at
its index from this function.

`s` can be given and is the laplace variable of investigation (``≈ iω``).
"""
function voltageDivision end
voltageDivision(::Impedor, s=0) = 1
voltageDivision(::Short, s=0) = 0
voltageDivision(::Open, s=0) = 1
voltageDivision(c::Parallel, s=0) = map(x -> voltageDivision(x, s), c)
function voltageDivision(c::Series, s=0)
    return voltageDivision.(c, s) .* impedance.(c, s) ./ sum(x -> impedance(x, s), c)
end
voltageDivision(::VoltageSource, s=0) = 0 # Or the other way around
voltageDivision(::CurrentSource, s=0) = 1 # Or the other way around

"""
```julia
currentDivision(component, s=0)
```
If a total current ``I`` is applied through `component`, the current through
respective sub-component is ``k·I``, where ``k`` is the coefficient return at
its index from this function.

`s` can be given and is the laplace variable of investigation (``≈ iω``).
"""
function currentDivision end
currentDivision(::Impedor, s=0) = 1
currentDivision(::Short, s=0) = 1
currentDivision(::Open, s=0) = 0
function currentDivision(c::Parallel, s=0)
    return (currentDivision.(c, s) ./ impedance.(c, s)) .* invsum(x -> impedance(x, s), c)
end
currentDivision(c::Series, s=0) = map(x -> currentDivision(x, s), c)
currentDivision(c::VoltageSource, s=0) = 1 # Or the other way around
currentDivision(c::CurrentSource, s=0) = 0 # Or the other way around
# Voltage and current division }}}

# Simplify {{{
function simplify(x::S, Greedy::Type, Shy::Type) where {S}
    types = unique(typeof.(x.l))
    any(types .<: Greedy) && return Greedy()
    all(types .<: Shy) && return Shy()
    l = Impedor[]
    for T in filter(t -> !<:(t, Shy), types)
        append!(l, simplify(T[filter(t -> isa(t, T), x.l)...], S))
    end
    return S(l)
end

simplify(x::Series, extra=nothing) = simplify(x, Open, Short)
simplify(x::Parallel, extra=nothing) = simplify(x, Short, Open)

simplify(x::Vector{<:Resistor}, ::Type{Parallel}) = [Resistor(invsum(getproperty.(x, :R)))]
simplify(x::Vector{<:Resistor}, ::Type{Series}) = [Resistor(sum(getproperty.(x, :R)))]
simplify(x::Vector{<:Capacitor}, ::Type{Parallel}) = [Capacitor(sum(getproperty.(x, :C)))]
simplify(x::Vector{<:Capacitor}, ::Type{Series}) = [Capacitor(invsum(getproperty.(x, :C)))]
simplify(x::Vector{<:Inductor}, ::Type{Parallel}) = [Inductor(invsum(getproperty.(x, :L)))]
simplify(x::Vector{<:Inductor}, ::Type{Series}) = [Inductor(sum(getproperty.(x, :L)))]
simplify(x::Vector{<:Series}, ::Type{Parallel}) = simplify.(x)
simplify(x::Vector{<:Parallel}, ::Type{Series}) = simplify.(x)
simplify(x::Vector{<:Short}, ::Type) = nothing
simplify(x::Vector{<:Open}, ::Type) = nothing
# Simplify }}}

# Extract network {{{
"""
```julia
Network(c::Circuit, a, b)
```
Using nodes `a` and `b` as terminals, traverse the circuit `c` and return a
`Series`, `Parallel` or simply a component that connects them.

This is going to be recursive as all hell.
"""
function Network(c::Circuit, a::CircuitIndex, b::CircuitIndex) end
# Extract network }}}

# Auxiliary functions {{{
# Reciprocal sum {{{
invsum(x) = inv(sum(inv, x))
invsum(f, x) = inv(sum(t -> inv(f(t)), x))
# }}}

# Unwind {{{
unwind!(l::Vector{Impedor}, ::Type{T}, x) where {T} = push!(l, x)
function unwind!(l::Vector{Impedor}, ::Type{T}, s::T) where {T}
    for x in s
        unwind!(l, T, x)
    end
end
# Unwind }}}
# Auxiliary functions }}}

# Printing functions {{{
function _printconnection(io, p1, p2, v)
    print(io, "\t(")
    join(io, p1, ',')
    print(io, ") to[")
    show(io, MIME"text/circuitikz"(), v)
    print(io, "] (")
    join(io, p2, ',')
    return print(io, ") %\n")
end

printconnection(io, p1, p2, v; expandnetworks=false) = _printconnection(io, p1, p2, v)

function printconnection(io, p1, p2, v::Series; expandnetworks=false)
    if !expandnetworks
        return _printconnection(io, p1, p2, v)
    end
    coords = collect(
        zip(
            range(p1[1], p2[1]; length=length(v) + 1),
            range(p1[2], p2[2]; length=length(v) + 1),
        ),
    )
    for (i, c) in enumerate(v)
        printconnection(io, coords[i], coords[i + 1], c; expandnetworks=true)
    end
end

function printconnection(io, p1, p2, v::Parallel; expandnetworks=false)
    if !expandnetworks
        return _printconnection(io, p1, p2, v)
    end
    l = 0.3 # Approximate length of a component, as a proportion of the total...
    w = 0.2 # Approximate width of a component, absolute...
    p1 = [p1...]
    p2 = [p2...]
    p3 = (1 / 2 + l) * p1 .+ (1 / 2 - l) * p2
    p4 = (1 / 2 - l) * p1 .+ (1 / 2 + l) * p2
    L = sqrt(sum((p2 .- p1) .^ 2))
    (c, s) = (p2 - p1) ./ L
    a1 = p3 .+ [s, -c] .* w * length(v) / 2
    a2 = p3 .+ [-s, c] .* w * length(v) / 2
    b1 = p4 .+ [s, -c] .* w * length(v) / 2
    b2 = p4 .+ [-s, c] .* w * length(v) / 2
    a = zip(range(a1[1], a2[1]; length=length(v)), range(a1[2], a2[2]; length=length(v)))
    b = zip(range(b1[1], b2[1]; length=length(v)), range(b1[2], b2[2]; length=length(v)))
    _printconnection(io, p1, p3, Short())
    _printconnection(io, p2, p4, Short())
    _printconnection(io, a1, a2, Short())
    _printconnection(io, b1, b2, Short())
    for (aa, bb, vv) in zip(a, b, v)
        printconnection(io, aa, bb, vv; expandnetworks=true)
    end
end
# Printing functions }}}

# Image {{{
"""
```julia
latexstandalone(c, "filename.png")
```
Save circuit `c` as a png image.
"""
function latexstandalone(c::Circuit, filename::AbstractString; kwargs...)
    temp = tempname()
    open(temp * ".tex", "w") do f
        print(
            f,
            raw"""
            \documentclass{standalone}
            \usepackage{circuitikz}
            \begin{document}
                \begin{tikzpicture}[x=4cm,y=4cm]
                    """,
        )
        show(f, MIME"text/circuitikz"(), c; kwargs...)
        print(
            f,
            raw"""
        \end{tikzpicture}
    \end{document}
    """,
        )
    end
    run(`xelatex --interaction=nonstopmode --output-dir=$(tempdir()) $temp.tex`)
    return run(
        `convert -density 300 $temp.pdf -background white -flatten -quality 90 $filename`
    )
end
# Image }}}

end


text:
#Weird fun stuff
msg = b"Hello, World!"

#=
total=0x0
for i=msg
    println(hex(total+=i))
end
=#
### Manips
"""
Since the end values beg it, add them.
"""
###
Char(msg[1] + msg[13])
###
"""Of course, an i, and we know H can be i, so
curiousity: space plus W?"""
###
function manip(a::Int, o::Int, mesg)
    Char(mesg[a] + mesg[o])
end

manip(7, 8, msg)

### Welllll, then, Are we on to a programmers joke!?
# Leave the 2index alone, because ie:
manip(3, 4, msg)
###
# now, o, or ocomma or osamma?? chill now
manip(5, 6, msg)
###Null and then a unicode control... I think they imply the letters are upside down and wrapped.
msg2 = "ieØ\u9b"
### NOTE: Google that code. Read the google book XD its interesting.

# Branch! Either `wo` or `or`
## `or` first
manip(9, 10, msg)

### BUT WAIT! the hex is 0xe1. Branch
manip(11, 12, msg)
### Yup. Thats the one!
msg3 = "we1Đ" #suspiciously like JonEmpr

###
msg4 = "$(msg2)$(msg3)"
### reverse?
msg5 = reverse(msg4)
### but clearly must flip if so
"ĐjEm\u9bØei"
### split Dz
"đEm\u9bØeid"
msg13 = join(msg2, msg3)
###

manip(8, 9, msg)
###

max_stars_repo_name: jempyre/Dionysus

max_issues_repo_name: jempyre/Dionysus

max_forks_repo_name: jempyre/Dionysus


text:
module Unfolding

using Clustering: dbscan
using DelimitedFiles
using Distances
using ImageMorphology: thinning
using Graphs: connected_components, dijkstra_shortest_paths
using LinearAlgebra: Diagonal, Symmetric, cross, dot, eigen
using MultivariateStats: PCA, dmat2gram, fit, projection
using NearestNeighbors
using Optim
using Random
using Setfield
using SimpleWeightedGraphs
using StatsBase: Weights, mean, mean!, quantile, sample
using WriteVTK

include("coords_optimization.jl")
include("data_handling.jl")
include("landmark_isomap.jl")
include("reference_points.jl")
include("unfold.jl")

export
    coords,
    errors,
    getreference,
    landmark_isomap,
    to_vtk,
    unfold
end


text:
"""
    get_label(s) -> String
Return the label/identifier.
"""
function get_label end

"""
    get_values(s) -> Vector
Return the current values.
"""
function get_values end

"""
    get_value(s)
Return the current value.
"""
function get_value end

"""
    get_string(s) -> String
Return the current string.
"""
function get_string end

"""
    get_color(s)
Return the current color.
"""
function get_color end

"""
    is_open(s) -> Bool
Return `true` when the widget is open.
"""
function is_open end


text:
module HTMLRenderer

import DataFrames
import JSON

import Dance.Configuration
import Dance.Logger
import Dance.PayloadUtils

"""
    populate(;html_file::String="", data::Union{DataFrames.DataFrame, Dict, String})

Populate supplied HTML with data, by replacing `@data` param
"""
function populate(;html_file::String="", data::Union{DataFrames.DataFrame, Dict, String}) :: String
    output_data::String = ""

    if isa(data, DataFrames.DataFrame)
        output_data = JSON.json(PayloadUtils.convert_dataframe_to_array(data))
    elseif isa(data, Dict)
        output_data = JSON.json(data)
    else
        output_data = data
    end

    html_output::String = read(html_file, String)
    html_output = replace(html_output, "@data" => output_data)

    return html_output
end

"""
    render(;headers::Dict{String, String}, status_code::Int16, data::Union{DataFrames.DataFrame, Dict, String}, html_file::String) :: Dict{Symbol, Union{Dict{String, String}, Int16, String}}

HTML renderer

`status code` is pre-supplied

Cannot set `headers type to `Dict{String, String} here, as can be blank (status_code !=200)
"""
function render(;headers::Dict{String, String}, status_code::Int16, data::Union{DataFrames.DataFrame, Dict, String}, html_file::String) :: Dict{Symbol, Union{Dict{String, String}, Int16, String}}
    if status_code==500
        Logger.log("500 Internal Server Error when rendering page with $data")
    end

    return Dict(
        :headers => headers,
        :status_code => status_code,
        :content_type => "text/html; charset=UTF-8",
        :body => populate(;html_file=html_file, data=data)
    )
end

end


text:
# MultiVector for CliffordAlgebras.jl

import Base.zero, Base.one, Base.iszero, Base.isone
import Base.==, Base.show, Base.eltype, Base.convert
import Base.getproperty, Base.propertynames, Base.conj
import Base.reverse, Base.~

"""
    MultiVector{CA,T,BI}

Type for a multivector belonging to the algebra CA<:CliffordAlgbra with vector coefficients of type T.
Coefficients are stored using a sparse coding, and only the coefficients of the basis indices stored in the tuple BI are considered.
"""
struct MultiVector{CA,T,BI,K}
    c::NTuple{K,T}
    function MultiVector(
        CA::Type{<:CliffordAlgebra},
        BI::NTuple{K,Integer},
        c::NTuple{K,T},
    ) where {K,T<:Real}
        @assert length(BI) > 0
        #@assert issorted(BI) && allunique(BI)
        new{CA,T,convert(NTuple{K,Int}, BI),K}(c)
    end
end

"""
    MultiVector(::CliffordAlgebra, a::Real)
    MultiVector(::Type{<:CliffordAlgebra}, a::Real)

Creates a MultiVector from the real number a with only a scalar component. The internal storage type of the MultiVector is the type of a.
"""
MultiVector(CA::Type{<:CliffordAlgebra}, a::T) where {T<:Real} = MultiVector(CA, (1,), (a,))
MultiVector(ca::CliffordAlgebra, a::T) where {T<:Real} = MultiVector(typeof(ca), a)

"""
    MultiVector(::CliffordAlgebra, v::NTuple{N,T}) where {N,T<:Real}
    MultiVector(::Type{<:CliffordAlgebra}, v::NTuple{N,T}) where {N,T<:Real}

Creates a MultiVector by converting the provided vector v to a 1-vector. The internal storage type of the MultiVector is T.
"""
function MultiVector(CA::Type{<:CliffordAlgebra}, v::NTuple{N,T}) where {N,T<:Real}
    @assert N == order(CA) "Dimension count mismatch."
    MultiVector(CA, Tuple(2:N+1), v)
end

MultiVector(ca::CliffordAlgebra, v::NTuple{N,T}) where {N,T<:Real} =
    MultiVector(typeof(ca), v)

zero(::Type{<:MultiVector{CA,T}}) where {CA,T} = MultiVector(CA, zero(T))
zero(mv::MultiVector) = zero(typeof(mv))

one(::Type{<:MultiVector{CA,T}}) where {CA,T} = MultiVector(CA, one(T))
one(mv::MultiVector) = one(typeof(mv))

iszero(mv::MultiVector) = all(iszero.(coefficients(mv)))
isone(mv::MultiVector) =
    baseindices(mv)[1] == 1 &&
    isone(coefficients(mv)[1]) &&
    all(iszero.(coefficients(mv)[2:end]))

(==)(a::MultiVector, b::MultiVector) = false

@generated function (==)(a::MultiVector{CA}, b::MultiVector{CA}) where {CA}
    bia = baseindices(a)
    bib = baseindices(b)
    bi = union(bia,bib)
    cond = foldr( (exl,exr) -> Expr(:&&, exl, exr), (
        begin
            ka = findfirst(isequal(i), bia)
            kb = findfirst(isequal(i), bib)
            if isnothing(ka)
                :(iszero(cb[$kb]))
            elseif isnothing(kb)
                :(iszero(ca[$ka]))
            else
                :(ca[$ka] == cb[$kb])
            end
        end
        for i in bi
    ))
    quote
        ca = coefficients(a)
        cb = coefficients(b)
        return $cond
    end
end

(==)(a::MultiVector{CA,Ta,BI}, b::MultiVector{CA,Tb,BI}) where {CA,Ta,Tb,BI} = coefficients(a) == coefficients(b)

(==)(a::MultiVector{CA}, b::Real) where CA = a == MultiVector(CA, b)
(==)(a::Real, b::MultiVector) = b == a

"""
    coefficients(::MultiVector)

Returns the sparse coefficients of the MultiVector.
"""
coefficients(mv::MultiVector) = getfield(mv,:c)

"""
    algebra(::MultiVector)
    algebra(::Type{<:MultiVector})

Returns the CliffordAlgebra instance to which the MultiVector belongs.
"""
algebra(::Type{<:MultiVector{CA}}) where {CA} = CA.instance
algebra(mv::MultiVector) = algebra(typeof(mv))

"""
    Algebra(::MultiVector)
    Algebra(::Type{<:MultiVector})

Returns the CliffordAlgebra type to which the MultiVector belongs.
"""
Algebra(::Type{<:MultiVector{CA}}) where {CA} = CA
Algebra(mv::MultiVector) = Algebra(typeof(mv))

eltype(::Type{<:MultiVector{CA,T}}) where {CA,T} = T
eltype(mv::MultiVector) = eltype(typeof(mv))

"""
    baseindices(::MultiVector)
    baseindices(::Type{<:MultiVector})

Returns the indices for the sparse MultiVector basis.
"""
baseindices(::Type{<:MultiVector{CA,T,BI}}) where {CA,T,BI} = BI
baseindices(mv::MultiVector) = baseindices(typeof(mv))

convert(T::Type{<:Real}, mv::MultiVector{CA,Tmv,(1,),1}) where {CA,Tmv} =
    convert(T, coefficients(mv)[1])

function convert(T::Type{<:Real}, mv::MultiVector{CA,Tmv,BI}) where {CA,Tmv,BI}
    if BI[1] == 1
        if all(iszero.(coefficients(mv)[2:end]))
            convert(T, coefficients(mv)[1])
        else
            throw(InexactError(:convert, T, mv))
        end
    else
        if all(iszero.(coefficients(mv)))
            zero(T)
        else
            throw(InexactError(:convert, T, mv))
        end
    end
end

"""
    scalar(mv::MultiVector)

Returns the scalar component of the multivector. The result if of the internal storage type eltype(mv).
"""
function scalar(mv::MultiVector{CA,T,BI}) where {CA,T,BI}
    if BI[1] == 1
        coefficients(mv)[1]
    else
        zero(T)
    end
end

"""
    prune(::MultiVector ; rtol = 1e-8 )

Returns a new MultiVector with all basis vectors removed from the sparse basis whose coefficients fall below the relative magnitude threshold.
This function is not type stable, because the return type depends on the sparse basis.
"""
function prune(mv::MultiVector; rtol = 1e-8)
    threshold = rtol * abs(maximum(coefficients(mv)))
    selector = findall(c -> abs(c) > threshold, coefficients(mv))
    if isempty(selector)
        zero(mv)
    else
        MultiVector(Algebra(mv), baseindices(mv)[selector], coefficients(mv)[selector])
    end
end

"""
    extend(::MultiVector)

Returns a new MultiVector with a non-sparse coefficient coding. This can be useful to manage type stability.
"""
@generated function extend(mv::MultiVector{CA}) where CA
    bi = baseindices(mv)
    d = dimension(CA)
    T = eltype(mv)
    bexpr = Expr(:call,:tuple)
    cexpr = Expr(:call,:tuple)
    for k = 1:d
        push!(bexpr.args, k)
        n = findfirst(isequal(k), bi)
        if isnothing(n)
            push!(cexpr.args, :(zero($T)))
        else
            push!(cexpr.args, :(coefficients(mv)[$n]))
        end
    end
    :(@inbounds MultiVector(CA, $bexpr, $cexpr))
end

"""
    grade(::MultiVector, k::Integer)

Projects the MultiVector onto the k-vectors.
"""
function grade(mv::MultiVector, k::Integer)
    ca = algebra(mv)
    selector = findall(isequal(k), map(i -> basegrade(ca, i), baseindices(mv)))
    if isempty(selector)
        zero(mv)
    else
        MultiVector(Algebra(mv), baseindices(mv)[selector], coefficients(mv)[selector])
    end
end

"""
    isgrade(::MultiVector, k::Integer)

Returns true if the MultiVector is of grade k, false if not.
"""
function isgrade(mv::MultiVector, k::Integer)
    ca = algebra(mv)
    all(basegrade(ca,i) == k || iszero(coefficients(mv)[n]) for (n,i) in enumerate(baseindices(mv)))
end

"""
    even(::MultiVector)

Returns the even grade projection of the MultiVector.
"""
function even(mv::MultiVector)
    ca = algebra(mv)
    selector = findall(iseven, map(i -> basegrade(ca, i), baseindices(mv)))
    if isempty(selector)
        zero(mv)
    else
        MultiVector(Algebra(mv), baseindices(mv)[selector], coefficients(mv)[selector])
    end
end

"""
    odd(::MultiVector)

Returns the odd grade projection of the MultiVector.
"""
function odd(mv::MultiVector)
    ca = algebra(mv)
    selector = findall(isodd, map(i -> basegrade(ca, i), baseindices(mv)))
    if isempty(selector)
        zero(mv)
    else
        MultiVector(Algebra(mv), baseindices(mv)[selector], coefficients(mv)[selector])
    end
end

"""
    grin(mv::MultiVector)

Returns the grade involution of the MultiVector, i.e. even(mv) - odd(mv).
"""
grin(mv::MultiVector) = even(mv) - odd(mv)

"""
    dual(mv::MultiVector)

Returns the Poincaré dual of the MultiVector, such that for all basis MultiVectors mv * dual(mv) = pseudoscalar. Dual is a linear map and the images of other MultiVectors follow from the images of the basis MultiVectors.
"""
dual(mv::MultiVector{CA,T,BI,K}) where {CA,T,BI,K} =
    MultiVector(CA, dimension(CA) + 1 .- BI[end:-1:1], coefficients(mv)[end:-1:1])

"""
    reverse(::MultiVector)

Returns the MultiVector that has all the basis vector products reversed.
"""
function reverse(mv::MultiVector)
    # Reverses the order of the canonical basis products
    CA = Algebra(mv)
    BI = baseindices(mv)
    s = map(n -> basereverse(CA, n), BI)
    MultiVector(CA, BI, coefficients(mv) .* s)
end

"""
    ~a
    (~)(::MultiVector)

Returns the reversed MultiVector reverse(a).
"""
(~)(mv::MultiVector) = reverse(mv)

"""
    conj(mv::MultiVector)

Return the conjugate of the MultiVector, i.e. reverse(grin(mv)).
"""
conj(mv::MultiVector) = reverse(grin(mv))

function show_multivector(io::IO, m::MultiVector{CA,T,BI,K}) where {CA,T,BI,K}
    if all(iszero.(coefficients(m)))
        print(io, 0)
    else
        for k = 1:K
            if !iszero(coefficients(m)[k])
                bs = basesymbol(CA, BI[k])
                if bs == Symbol(:𝟏)
                    if coefficients(m)[k] < 0
                        print(io, "-", -coefficients(m)[k])
                    else
                        print(io, "+", coefficients(m)[k])
                    end
                else
                    if coefficients(m)[k] < 0
                        print(io, "-", -coefficients(m)[k], "×", bs)
                    else
                        print(io, "+", coefficients(m)[k], "×", bs)
                    end
                end
            end
        end
        print(io, " ∈ Cl", signature(CA))
    end
end

function show(io::IO, m::MultiVector)
    show_multivector(io, m)
end

"""
    basevector(::CliffordAlgebra, n::Integer)
    basevector(::Type{<:CliffordAlgebra}, n::Integer)

Returns the n-th basis MultiVector of the given CliffordAlgebra.
"""
basevector(CA::Type{<:CliffordAlgebra}, n::Integer) = MultiVector(CA, (n,), (1,))
basevector(ca::CliffordAlgebra, n::Integer) = basevector(typeof(ca), n)

"""
    basevector(::CliffordAlgebra, name::Symbol)
    basevector(::Type{<:CliffordAlgebra}, name::Symbol)

Returns the basis MultiVector with the specified name from the given Clifford Algebra.
"""
function basevector(CA::Type{<:CliffordAlgebra}, name::Symbol)
    baseindex = findfirst(isequal(name), ntuple(k -> basesymbol(CA, k), dimension(CA)))
    if isnothing(baseindex)
        error("Algebra does not have a basis element ", name)
    end
    basevector(CA, baseindex)
end

basevector(ca::CliffordAlgebra, name::Symbol) = basevector(typeof(ca), name)

propertynames(ca::CliffordAlgebra) = ntuple(i -> basesymbol(ca, i), dimension(ca))
propertynames(mv::MultiVector) = propertynames(algebra(mv))

function getproperty(ca::CliffordAlgebra, name::Symbol)
    basevector(ca, name)
end

function getproperty(mv::MultiVector, name::Symbol)
    ca = algebra(mv)
    baseindex = findfirst(isequal(name), ntuple(k -> basesymbol(ca, k), dimension(ca)))
    if isnothing(baseindex)
        error("Algebra does not have a basis element ", name)
    end
    storageindex = findfirst(isequal(baseindex), baseindices(mv))
    if isnothing(storageindex)
        return zero(eltype(mv))
    else
        return coefficients(mv)[storageindex]
    end
end

"""
    pseudoscalar(::CliffordAlgebra)
    pseudoscalar(::Type{<:CliffordAlgebra})

Returns the pseudoscalar of the given algebra.
"""
pseudoscalar(CA::Type{<:CliffordAlgebra}) = MultiVector(CA, (dimension(CA),), (1,))
pseudoscalar(ca::CliffordAlgebra) = pseudoscalar(typeof(ca))

"""
    vector(::MultiVector)

Returns the non-sparse vector representation of the MutliVector.
"""
function vector(mv::MultiVector)
    ca = algebra(mv)
    d = dimension(ca)
    T = eltype(mv)
    V = zeros(T, d)
    V[collect(baseindices(mv))] .= coefficients(mv)
    V
end

"""
    matrix(::MultiVector)

Returns the matrix algebra representation of the MultiVector.
"""
function matrix(mv::MultiVector)
    ca = algebra(mv)
    d = dimension(ca)
    T = eltype(mv)
    M = zeros(T, d, d)
    for (c, b) in zip(coefficients(mv), baseindices(mv))
        for bi = 1:d
            (bo, mc) = baseproduct(ca, b, bi)
            M[bo, bi] += c * mc
        end
    end
    M
end

max_stars_repo_name: ATell-SoundTheory/CliffordAlgebras

max_issues_repo_name: ATell-SoundTheory/CliffordAlgebras


text:
using Pushover

include("config.jl")

client = PushoverClient(CONFIG["USER_KEY"], CONFIG["API_TOKEN"])
message = "My first message"
response = send(client, message, priority=1)
println("response: $response")


text:
"""
    AbstractStar{N}

Abstract supertype for all star set types.

### Notes

A set ``X`` is star-like (also known as generalized star) if it can be represented
by a center ``x₀ ∈ \\mathbb{R}^n`` and ``m`` vectors ``v₁, …, vₘ`` forming the basis,
and a predicate ``P : \\mathbb{R}^n → \\{⊤, ⊥\\}`` such that

```math
    X = \\{x ∈ \\mathbb{R}^n : x = x₀ + \\sum_{i=1}^m α_i v_i,,~~\\textrm{s.t. } P(α) = ⊤ \\}.
```
"""
abstract type AbstractStar{N} end

isoperationtype(::Type{<:AbstractStar}) = false
isconvextype(::Type{<:AbstractStar}) = false


text:
# bkamins: we might keep here the code as previously defined
try
    using ProgressMeter
catch
    import Pkg
    Pkg.add("ProgressMeter")
    using ProgressMeter
end

include("common.jl")

function tabu_search(rs::RideShare; tabu_tenure=10, max_iterations=100)
    initial_solution = get_initial_solution(rs)
    initial_cost = rideshare_optimality(rs, initial_solution)

    # If you'd like to start with predetermined solution
    # comment the previous line and intialize the following paratmeters:
    # initial_solution = [1,2,4,3,5]
    # initial_cost = 35
    # solutions_list = [initial_cost]

    println("---------------------------------------------------------------")
    println("-------- INITIAL SOLUTION: $initial_solution")
    println("-------- INITIAL COST: $initial_cost")
    println("----------------------------------------------------------------")

    num_nodes = mapreduce(length, +, initial_solution, init=length(initial_solution))

    # Tabu list intialization to zero.
    tabu_list = zeros(Int,num_nodes,num_nodes)

    current_solution = initial_solution # The current solution is the intial solution.
    best_solution = initial_solution    # The best solution is the intial solution.
    best_cost = initial_cost            # The min. cost is the cost of the intial solution.
    solutions_list = Float64[]

    for i in 1:max_iterations
        println("\n--------------- ITERATION $i ---------------")
        # Obtaining best neighboring solution.
        best_neighbourhood_solution, best_neighbourhood_cost =
            get_neighbourhood!(rs,current_solution, best_cost, tabu_list,
                               tabu_tenure, solutions_list)

        # The obtained neighboring solution is the current solution.
        current_solution = best_neighbourhood_solution

    	# Comparing if it's the best solution so far.
        if (best_neighbourhood_cost > best_cost)
            best_solution = best_neighbourhood_solution
            best_cost = best_neighbourhood_cost
            # bkamins: why is this commented out?, append! would be better
            #solutions_list = [solutions_list best_neighbourhood_cost]
        end
    end

    println("-----------------------------------------------------------------")
    println("------- THE BEST SOLUTION OBTAINED IN $max_iterations ITERATIONS:")
    foreach(println, best_solution)
    println("-------- COST OF THE BEST SOLUTION: $best_cost")
    println("-------- THE LIST OF SOLUTIONS: $solutions_list")
    println("--------------------------------------------------------------------")
    (solutions_list, best_solution)
end

```
Function that obtains the best neighboring solution by realzing a set of
modifications in the current solution.
Generate different neighboring solutions by swapping and keep the solution with min. cost.
Input parameters:
  - current_solution: current solution.
  - best_cost: cost of the best solution obatined so far.
  - tabu_tenure: number of iterations a swapping will be in the tabu list.
  - tabu_list: Tabu list.
  - cost_matrix: Mcost matrix.
Output parameters:
  - best_neighbourhood_solution: best neighboring solution obtained.
  - best_neighbourhood_cost: cost of the best neighboring solution obatined.
Mutates the `tabu_list` and `solutions_list`.
```
function get_neighbourhood!(rs::RideShare, current_solution, best_cost, tabu_list,
                            tabu_tenure, solutions_list)
    println("get_neighbourhood tabu_list= $tabu_list")
    println("\nTHE BEST KNOWN SOLUTION COST: $best_cost")
    println("\nCURRENT SOLUTION $current_solution ")

    push!(solutions_list,best_cost)

    best_neighbourhood_solution = current_solution
    best_neighbourhood_cost = 0.0
    best_node1, best_node2 = 0, 0

    min_cost = 0.0
    node_count = length(current_solution)

    for y in 1:node_count
        for i in 1:length(current_solution[y])
            # Obtaining all possible neighboring solutions.
            for j in (i+1):length(current_solution[y])
                neighbourhood_solution = deepcopy(current_solution)
                if rand() > 0.6
                    temp = neighbourhood_solution[y][i]
                    neighbourhood_solution[y][i] = neighbourhood_solution[y][j]
                    neighbourhood_solution[y][j] = temp
                else
                    next = min(y + 1, node_count)
                    index1 = min(i, length(neighbourhood_solution[y]))
                    index2 = min(j, length(neighbourhood_solution[next]))

                    temp = neighbourhood_solution[y][index1]
                    neighbourhood_solution[y][index1] = neighbourhood_solution[next][index2]
                    neighbourhood_solution[next][index2] = temp
                end

                println("- CANDIDATE neighbourhood SOLUTION: $neighbourhood_solution")

                # Checking that the swap is not in the tabu.
                neighbourhood_cost = rideshare_optimality(rs, neighbourhood_solution)
                # Penalizing the moves that are more frequent for diversifying the search.
                #println(neighbourhood_solution[y][i]," ",neighbourhood_solution[y][j]," ",size(tabu_list))
                swapping_frequency = get_swapping_frequency(neighbourhood_solution[y][i],
                                                            neighbourhood_solution[y][j],
                                                            tabu_list)
                diversification_cost = neighbourhood_cost + swapping_frequency

                if !is_tabu_solution(neighbourhood_solution[y][i],neighbourhood_solution[y][j],tabu_list)
                    # Is not a tabued solution.

                    println("--- COST: $neighbourhood_cost + $swapping_frequency = $diversification_cost \n")

                    if (min_cost == 0) || (diversification_cost > min_cost)
                        # best solution obatined so far
                        min_cost = diversification_cost
                        best_neighbourhood_solution = neighbourhood_solution
                        best_neighbourhood_cost = neighbourhood_cost
                        best_node1 = neighbourhood_solution[y][i]
                        best_node2 = neighbourhood_solution[y][j]
                    end
                else
                    # Is a tabued solution:
                    # To avoid stagnation, apply asipration criteria
                    # If the cost of the solution is less that the cost of best solution obatined so far, accept this solution
                    if (diversification_cost > best_cost)
                        # best solution obatined so far.
                        min_cost = diversification_cost
                        best_neighbourhood_solution = neighbourhood_solution
                        best_neighbourhood_cost = neighbourhood_cost
                        best_node1 = neighbourhood_solution[y][i]
                        best_node2 = neighbourhood_solution[y][j]
                        println("- TABU SOLUTION ALLOWED - ASPIRATION CRITERIA: $neighbourhood_solution")
                        println("- ALLOWED TABU COST: $neighbourhood_cost + $swapping_frequency = $diversification_cost")
                    else
                        # Tabued solution is not permited.
                        println("- IS A TABU neighbourhood SOLUTION: $neighbourhood_solution")
                        println("--- TABU COST: $neighbourhood_cost + $swapping_frequency = $diversification_cost")
                    end
                end
            end
        end
    end

    # afterm obtaining the best neighbourhood solution, update the tabu list
    replace!(x -> x > 0 ? x - 1 : x, tabu_list)
    println("\nADD ($best_node1,$best_node2) TO TABU LIST: ")
    if best_node1 > 0 && best_node2 > 0
        add_swapping_tabu_list!(best_node1,best_node2,tabu_list,tabu_tenure)
    end

    println("tabu_list= $tabu_list")
    (best_neighbourhood_solution, best_neighbourhood_cost)
end

```
Adds a swapping to the tabu list controlling the frequency of this swapp.
Input parameters:
  - node1, node2: swapping nodes.
  - tabu_list: tabu list.
  - tabu_tenure: tabu tenure.
```
function add_swapping_tabu_list!(node1, node2, tabu_list, tabu_tenure)
    tabu_list[min(node1,node2),max(node1,node2)] = tabu_tenure
    tabu_list[max(node1,node2),min(node1,node2)] += 1
end

```
Checks the solution is listed as tabued.
Input parameters:
  - node1, node2: swapping nodes.
  - tabu_list: tabu list.
```
is_tabu_solution(node1, node2, tabu_list) =
    tabu_list[min(node1, node2), max(node1, node2)] > 0

```
Gets the swapping frequency
Input parameters:
  - node1, node2: swapping nodes.
  - tabu_list: tabu list.
```
get_swapping_frequency(node1, node2, tabu_list) =
    tabu_list[max(node1, node2), min(node1, node2)]

```
Function to obtain the nearest nodes to the current one that has not been visited before
Input parameters:
  - node_cost_list: vector of the costs of the current node.
  - initial_path: path obatined so far.
Output Parameters:
  - nearest_node: nearest node.
  - min_cost: cost to go to the nearest node.
```
function get_nearest_node(node_cost_list, initial_path)

    num_nodes = length(node_cost_list) # Number of nodes.
    visited_nodes = Set{Int}(initial_path)
    min_cost = 0 # Minimum cost.
    nearest_node = 0 # Selected node.

    for node=1:num_nodes
        # Checking that we have not visited this node before.
        if node in visited_nodes
            # Not visted node
            if min_cost == 0 || node_cost_list(node) < min_cost
                # The nearest node so far.
                min_cost = node_cost_list(node)
                push!(visited_nodes, node)
                nearest_node = node
            end
        end
    end
    (nearest_node, min_cost)
end

using Random
#Random.seed!(0)

res = tabu_search(rs_samples[1]; max_iterations=1000,tabu_tenure=10)
res = tabu_search(rs_samples[2]; max_iterations=20)


text:
# Stocks/News

"""
    news(conn::Connection, symbol::String; last::Int=10

Provides intraday news from over 3,000 global news sources including major
publications, regional media, and social.. This endpoint returns up to the last
50 articles. Use the [historical news](https://iexcloud.io/docs/api/#historical-news)
endpoint to fetch news as far back as January 2019

Path Parameters:

|Option|Description|
|:-----|:----------|
|symbol|A stock symbol|
|last  |Number between 1 and 50. Default is 10|
"""
function news(conn::Connection, symbol::String; last::Int=10)
    path_params = [:symbol, :last]
    last =  max(1, min(50, last))
    return get_stocks(conn, "news", path_params; symbol = symbol, last = last)
end

max_stars_repo_name: GodolphinCapitalManagement/Iex

max_issues_repo_name: GodolphinCapitalManagement/Iex

max_forks_repo_name: GodolphinCapitalManagement/Iex


text:
export AffineChartSystem, on_affine_chart

"""
    AffineChartSystem(F::AbstractSystem, v::PVector{T,N})

Given a system ``F(x): (ℙ^{m_1} × ⋯ × ℙ^{m_N}) → ℂⁿ`` this creates a new affine
system ``F′`` which operates on the affine chart defined by the vector
``v ∈ ℙ^{m_1} × ⋯ × ℙ^{m_N}`` and the augmented conditions ``vᵀx = 1``.
"""
struct AffineChartSystem{S<:AbstractSystem,N} <: AbstractSystem
    system::S
    chart::PVector{ComplexF64,N}
end

ModelKit.variables(F::AffineChartSystem) = variables(F.system)
ModelKit.parameters(F::AffineChartSystem) = parameters(F.system)
ModelKit.variable_groups(F::AffineChartSystem) = variable_groups(F.system)

"""
    on_affine_chart(F::Union{System,AbstractSystem}, dimensions)

Construct an `AffineChartSystem` on a randomly generated chart `v`. Each entry is drawn
idepdently from a univariate normal distribution.
"""
on_affine_chart(F::System, dims = nothing) = on_affine_chart(ModelKitSystem(F), dims)
function on_affine_chart(F::AbstractSystem, dims = nothing)
    vargroups = variable_groups(F)
    if vargroups === nothing
        dims = [size(F, 2) - 1]
    else
        dims = length.(vargroups,) .- 1
    end
    chart = PVector(randn(ComplexF64, sum(dims) + length(dims)), tuple(dims...))
    AffineChartSystem(F, chart)
end

function Base.size(F::AffineChartSystem{<:AbstractSystem,N}) where {N}
    m, n = size(F.system)
    (m + N, n)
end

function evaluate_chart!(u, v::PVector{<:Any,N}, x::AbstractVector) where {N}
    ranges = dimension_indices(v)
    n = length(u) - N
    for (k, range) in enumerate(ranges)
        out = zero(promote_type(eltype(u), eltype(x)))
        @inbounds for i in range
            out += v[i] * x[i]
        end
        u[n+k] = out - 1.0
    end
    nothing
end

function jacobian_chart!(U, v::PVector{<:Any,N}, x::AbstractVector) where {N}
    ranges = dimension_indices(v)
    n = size(U, 1) - N
    for j = 1:size(U, 2), i = (n+1):size(U, 1)
        U[i, j] = zero(eltype(U))
    end
    for (k, range) in enumerate(ranges)
        for j in range
            U[n+k, j] = v[j]
        end
    end
    nothing
end

function (F::AffineChartSystem{<:Any,N})(x::AbstractVector, p = nothing) where {N}
    v = PVector(x, dims(F.chart))
    u = F.system(x, p)
    append!(u, zeros(N))
    evaluate_chart!(u, F.chart, v)
    u
end
function (F::AffineChartSystem{<:Any,N})(x, p = nothing) where {N}
    u = F.system(x, p)
    append!(u, zeros(N))
    evaluate_chart!(u, F.chart, x)
    u
end

function evaluate!(u, F::AffineChartSystem{<:Any,N}, x, p = nothing) where {N}
    evaluate!(u, F.system, x)
    evaluate_chart!(u, F.chart, x)
    u
end

function evaluate_and_jacobian!(
    u,
    U,
    F::AffineChartSystem{<:Any,N},
    x,
    p = nothing,
) where {N}
    evaluate_and_jacobian!(u, U, F.system, x)
    evaluate_chart!(u, F.chart, x)
    jacobian_chart!(U, F.chart, x)
    nothing
end

function taylor!(u, v::Val, F::AffineChartSystem, tx, p = nothing)
    u .= zero(eltype(u))
    taylor!(u, v, F.system, tx, p)
    # affine chart part is always zero since it is an affine linear form
    u
end


text:
#-------------------------------------------------------------------------------
# File: main.jl
# Description: This files contains all functions that are used for experiment.
# Date: November 17, 2019
# Authors: Killian Fretaud, Rémi Garcia,
#-------------------------------------------------------------------------------

using JuMP
using Random

#--------------------------------------------------
#
#               Choose a solver
#
#using Cbc; const OPTIMIZER_SELECTED = Cbc.Optimizer
#using Gurobi; const OPTIMIZER_SELECTED = Gurobi.Optimizer
using CPLEX; const OPTIMIZER_SELECTED = CPLEX.Optimizer
#using GLPK; const OPTIMIZER_SELECTED = GLPK.Optimizer
#
#--------------------------------------------------

# Instance & structures
include("instances.jl")
include("data.jl")
include("model.jl")
include("genetic.jl")
include("output.jl")

"""
    params_exact:
        time limit in seconds

    params_genetic:
        probability of crossover
        probability of mutation
        population size
        number of generations
        number of constructions
"""
function solve(instance;
               solve_exact = true, params_exact = (Float64(60*20), ),
               use_genetic = true, params_genetic = (0.8, 0.2, 100, 100, 5),
               print_solutions = false, print_times = true)
    if solve_exact
        println("Exact:")
        model, vars = get_model_from_instance(instance)
        set_time_limit_sec(model, params_exact[1])
        time_for_solving = @timed optimize!(model)
        if print_times
            println("\tTime: ", time_for_solving[2])
        end
        if print_solutions
            if termination_status(model) == MOI.OPTIMAL
                print_solution(solve_to_represent(instance, objective_value(model), vars))
            elseif termination_status(model) == MOI.TIME_LIMIT && has_values(model)
                println("\tSolution is not proved optimal")
                print_solution(solve_to_represent(instance, objective_value(model), vars))
            else
                println("\tNo solution found")
            end
        end
    end
    if use_genetic
        println("Genetic:")
        time_for_solving = @timed genetic(instance, params_genetic[1], params_genetic[2], params_genetic[3], params_genetic[4], params_genetic[5])
        if print_times
            println(time_for_solving[2])
        end
    end

    return
end

function main()
    list_instances, _ = data()
    for instance in list_instances
        println("Instance:\tnb_jobs = "*string(instance.nb_jobs)*"\tnb_machines = "*string(instance.nb_machines))
        solve(instance, params_exact = (1200.0, ), use_genetic = false, print_solutions = true)
        println()
    end

    return
end

max_stars_repo_name: k-fretaud/Flowshop-robotic-cell

max_issues_repo_name: k-fretaud/Flowshop-robotic-cell

max_forks_repo_name: k-fretaud/Flowshop-robotic-cell


text:
function luc_rc_seeder{T<:Integer}(n::T)
    a = zeros(BigInt, n)
    a[1] = 3
    a[2] = -1
    return a
end

function luc_rc{T<:Integer}(n::T, k::T)
    NFib(n, k, luc_rc_seeder)
end

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
# In this example we solve a robust linear programming problem using Optim. The problem is taken from [wikipedia](https://en.wikipedia.org/wiki/Robust_optimization#Example_1)

# $$\text{maximize}_{x,y} \; 3x+2y \quad \text{s.t}. x,y > 0, \quad cx+dy < 10 ∀ c,d ∈ P$$

# Where $c$ and $d$ are uncertain. We encode the constraint into the cost and solve it using 4 different algorithms

using MonteCarloMeasurements, Optim, ForwardDiff, Zygote

const c = 1 ∓ 0.1 # These are the uncertain parameters
const d = 1 ∓ 0.1 # These are the uncertain parameters
# In the cost function below, we ensure that $cx+dy > 10 \; ∀ \; c,d ∈ P$ by looking at the worst case
Base.findmax(p::AbstractParticles;dims=:) = findmax(p.particles,dims=:)
function cost(pars)
    x,y = pars
    -(3x+2y) + 10000sum(pars .< 0) + 10000*(maximum(c*x+d*y) > 10)
end

pars = [1., 1] # Initial guess
cost(pars)     # Try the cost function
cost'(pars)
# We now solve the problem using the following list of algorithms
function solvemany()
    algos = [NelderMead(), SimulatedAnnealing(), BFGS(), Newton()]
    map(algos) do algo
        res = Optim.optimize(cost, cost', pars, algo, inplace=false)
        m = res.minimizer
        cost(m)
    end
end
solvemany()'

# All methods find more or less the same minimum, but the gradient-free methods actually do a bit better
# How long time does it take to solve all the problems?
@time solvemany();
# It was quite fast

# We can also see whether or not it's possible to take the gradient of
# 1. An deterministic function with respect to determinisitc parameters
# 2. An deterministic function with respect to uncertain parameters
# 3. An uncertain function with respect to determinisitc parameters
# 4. An uncertain function with respect to uncertain parameters
function strange(x,y)
    (x.^2)'*(y.^2)
end
deterministic = [1., 2] # Initial guess
uncertain = [1., 2] .+ 0.001 .* StaticParticles.(10) # Initial guess
ForwardDiff.gradient(x->strange(x,deterministic), deterministic)
#
ForwardDiff.gradient(x->strange(x,deterministic), uncertain)
#
ForwardDiff.gradient(x->strange(x,uncertain), deterministic)
#
a = ForwardDiff.gradient(x->strange(x,uncertain), uncertain);
# mean.(a)
# The last one here is commented because it sometimes segfaults. When it doesn't, it seems to produce the correct result with the complicated type Particles{Particles{Float64,N},N}, which errors when printed.

# We can also do the same using Zygote. The result is the same, and Zygote also handles the last version without producing a weird type in the result!
using Zygote
Zygote.gradient(x->strange(x,deterministic), deterministic)
#
Zygote.gradient(x->strange(x,deterministic), uncertain)
#
Zygote.gradient(x->strange(x,uncertain), deterministic)
#
Zygote.gradient(x->strange(x,uncertain), uncertain)


text:
module Cluster

using Clustering: MinimalDistance, nnodes, nearest_neighbor, update_distances_upon_merge!,
                  push_merge!, HclustMerges, orderbranches_r!, Hclust

"""
Code copied from `Clustering.jl` but this saves RAM by:
* working in place
* using views

---

Efficient single link algorithm, according to Olson, O(n^2), fig 2.
Verified against R's implementation, correct, and about 2.5 x faster
For each i < j compute D(i,j) (this is already given)
For each 0 < i ≤ n compute Nearest Neighbor NN(i)
Repeat n-1 times
  find i,j that minimize D(i,j)
  merge clusters i and j
  update D(i,j) and NN(i) accordingly
"""
@views function single_linkage!(d::AbstractMatrix{T}) where {T<:Real}
    mindist = MinimalDistance(d)
    hmer = HclustMerges{T}(size(d, 1))
    n = nnodes(hmer)
    ## For each 0 < i ≤ n compute Nearest Neighbor NN[i]
    NN = [nearest_neighbor(d, i, n)[1] for i in 1:n]
    ## the main loop
    trees = collect(-(1:n))  # indices of active trees, initialized to all leaves
    while length(trees) > 1  # O(n)
        # find a pair of nearest trees, i and j
        i = 1
        NNmindist = i < NN[i] ? d[i, NN[i]] : d[NN[i], i]
        for k in 2:length(trees) # O(n)
            dist = k < NN[k] ? d[k, NN[k]] : d[NN[k], k]
            if dist < NNmindist
                NNmindist = dist
                i = k
            end
        end
        j = NN[i]
        if i > j
            i, j = j, i     # make sure i < j
        end
        last_tree = length(trees)
        update_distances_upon_merge!(d, mindist, i -> 0, i, j, last_tree)
        trees[i] = push_merge!(hmer, trees[i], trees[j], NNmindist)
        # reassign the last tree to position j
        trees[j] = trees[last_tree]
        NN[j] = NN[last_tree]
        pop!(NN)
        pop!(trees)
        ## update NN[k]
        for k in eachindex(NN)
            if NN[k] == j        # j is merged into i (only valid for the min!)
                NN[k] = i
            elseif NN[k] == last_tree # last_tree is moved into j
                NN[k] = j
            end
        end
        ## finally we need to update NN[i], because it was nearest to j
        NNmindist = typemax(T)
        NNi = 0
        for k in 1:(i - 1)
            if (NNi == 0) || (d[k, i] < NNmindist)
                NNmindist = d[k, i]
                NNi = k
            end
        end
        for k in (i + 1):length(trees)
            if (NNi == 0) || (d[i, k] < NNmindist)
                NNmindist = d[i, k]
                NNi = k
            end
        end
        NN[i] = NNi
    end
    orderbranches_r!(hmer)
    return Hclust(hmer, :single)
end
end # module


text:
module InvariantEnsembles
    using ApproxFun

export samplelegendrespectra,dotplot,spectradatabase,sampleensemblespectra,iekernel,samplespectra,sampleguespectra
export orthonormalpolynomials,orthonormalpolynomialsvalues,legendrepolynomials,scaledhermitepolynomials
export InvariantEnsemble,InvariantEnsembleUnscaled

## Construct OPs

function orthonormalpolynomials(μ0,α::Vector,β::Vector,d)
    n=length(α)+1

    p=Array(IFun{Float64,Interval{Float64}},n)
    p[1] = Fun([μ0],d)
    p[2] = multiplybyx(p[1])./β[1] - p[1].*α[1]./β[1]
    for k = 3:n
       p[k] =  multiplybyx(p[k-1])./β[k-1] - p[k-1].*α[k-1]./β[k-1] - p[k-2].*β[k-2]./β[k-1]
    end
    p
end

function orthonormalpolynomials(μ0,α::Function,β::Function,d,n)
    orthonormalpolynomials(μ0,map(α,[1:n-1]),map(β,[1:n-1]),d)
end

function legendrepolynomials(n)
  orthonormalpolynomials(1./sqrt(2),k->0,k->sqrt(k^2./(4k^2-1)),[-1.,1.],n)
end
function scaledhermitepolynomials(n)
  orthonormalpolynomials(n^(1/4)/(1.π)^(1/4),k->0,k->sqrt((k)/(2n)),[-3.,3.],n)
end

function orthonormalpolynomialsvalues(μ0,α::Vector,β::Vector,x)
    n=length(α)+1
    m=length(x)

    p=Array(Float64,m,n)

    p[:,1] = μ0*ones(m)
    p[:,2] = x.*p[:,1]./β[1] - p[:,1].*α[1]./β[1]
    for k = 3:n
       p[:,k] =  x.*p[:,k-1]./β[k-1] - p[:,k-1].*α[k-1]./β[k-1] - p[:,k-2].*β[k-2]./β[k-1]
    end
    p
end

## Ensembles

type InvariantEnsemble{D<:Interval}
    basis::Array{Float64,2}
    domain::D
end

InvariantEnsemble(basis,d::Vector)=InvariantEnsemble(basis,Interval(d))

#Takes in list of OPs, constructs phis
# can be unstable for large n
function InvariantEnsemble(p::Array{IFun},V::Function,d,n::Integer)
    error("Reimplement with matrix")

#     wsq=IFun(x->exp(-n/2.*V(x)),d)
#
#     #We now extend the lengths
#     m=length(wsq)+2n
#     p=map(f->pad(f,m),p)
#
#     # We want to multiply, but in value space to
#     # take advantage of wsq being very small
#
#     wsqv=exp(-n/2.*V(points(wsq.domain,m)))
#     q=map(f->IFun(chebyshevtransform(wsqv.*values(f)),f.domain),p)
#
#     InvariantEnsemble(q)

end

function adaptiveie(w,μ0,α,β,d)
  for logn = 4:20
    m=2^logn + 1
    pts=points(Interval(d),m)
    pv=orthonormalpolynomialsvalues(μ0,α,β,pts)

    wv=w(pts)

    cfs=chebyshevtransform(pv[:,end].^2.*wv)

    if maximum(abs(cfs[end-8:end])) < 200*eps()
        ## chop to minimize oversample

        m=length(chop!(cfs,200*eps()))

        pts=points(Interval(d),m)
        pv=orthonormalpolynomialsvalues(μ0,α,β,pts)
        wv=w(pts)

        return InvariantEnsemble(diagm(sqrt(wv))*pv,d)
    end
  end

  error("Did not converge")
end

#Reads in recurrence relationship and constructs OPs
function InvariantEnsemble(str::String,V::Function,d,n::Integer)
    file = Pkg.dir("InvariantEnsembles/CoefficientDatabase/" * str * "/" * string(n))
    μ0=readdlm(file * "norm.csv")[1]
    A=readdlm(file * "rc.csv",',')
    a=reshape((A[1,1:end-1]),size(A)[2]-1)
    b=reshape(A[2,2:end],size(A)[2]-1)

    adaptiveie(x->exp(-n.*V(x)),μ0,a,sqrt(b),d)
end

function InvariantEnsembleUnscaled(str::String,V::Function,d,n::Integer)
    file = Pkg.dir("InvariantEnsembles/CoefficientDatabaseUnscaled/" * str * "/")
    μ0=readdlm(file * "norm.csv")[1]
    A=readdlm(file * "rc.csv",',')
    a=reshape((A[1,1:end-1]),size(A)[2]-1)
    b=reshape(A[2,2:end],size(A)[2]-1)

    adaptiveie(x->exp(-V(x)),μ0,a[1:n-1],sqrt(b[1:n-1]),d)
end

#Decides whether to use built in recurrence or read it in
# Also contains ensemble data
function InvariantEnsemble(str::String,n::Integer)
    if(str == "Gaussian")
        InvariantEnsemble(str,x->x.^2,[-3.,3.],n)
    elseif(str == "Quartic")
        InvariantEnsemble(str,x->x.^4,[-3.,3.],n)
    elseif(str == "Eight")
        InvariantEnsemble(str,x->x.^8,[-3.,3.],n)
    elseif(str == "HODecay")
        InvariantEnsemble(str,x->x.^4/20 -4/15*x.^3 + x.^2/5+8/5*x,[-4.,6.],n)
    elseif(str == "Legendre")
        error("We need to reimplement Legendre")
        #InvariantEnsembles(map(f->pad(f,2n),legendrepolynomials(n)))
    elseif(str == "CoshUnscaled")
        InvariantEnsembleUnscaled("Cosh",x->cosh(x),[-2acosh(1.n),2acosh(1.n)],n)
    elseif(str == "EightUnscaled")
        InvariantEnsembleUnscaled("Eight",x->x.^8,[-3.n^(1/8),3.n^(1/8)],n)
    elseif(str == "QuarticUnscaled")
        InvariantEnsembleUnscaled("Quartic",x->x.^4,[-3.n^(1/4),3.n^(1/4)],n)
    end
end

## Sampling

iekernel(q::Array{Float64,2},d)=iekernel(q,d,plan_chebyshevtransform(q[:,1]))
function iekernel(q::Array{Float64,2},d,plan::Function)
    n=size(q)[1]
    m=size(q)[2]
    ret=zeros(n)
    for i = 1:m
        for k = 1:n
            ret[k] += q[k,i].*q[k,i]
        end
    end

  IFun(chebyshevtransform(ret,plan),d)
end

samplespectra(str::String,n::Integer,m::Integer)=samplespectra(InvariantEnsemble(str,n),m)

function samplespectra(p::InvariantEnsemble,m::Integer)
    q = p.basis
    plan = plan_chebyshevtransform(q[:,1])
    pts=chebyshevpoints(size(q,1))

    hcat([samplespectra(p.basis,p.domain,plan,pts) for i=1:m]...)'
end

samplespectra(q::Array{Float64,2},d)=samplespectra(q,d,plan_chebyshevtransform(q[:,1]),chebyshevpoints(size(q,1)))

function samplespectra(q::Array{Float64,2},d,plan::Function,pts)
    n = size(q,2)
    r=Array(Float64,n)

    for k=1:n-1
        m = n - k + 1
        r[k] = samplecdf(normalizedcumsum!(iekernel(q,d,plan).coefficients/m))
        f=Float64[bary(q[:,j],pts,r[k]) for j = 1:m]
        r[k] = fromcanonical(d,r[k])
        Q=null(f')
        q=q*Q
    end

    r[n] = sample(iekernel(q,d,plan))

    r
end

function iekernel(p::Array{IFun{Float64,Interval{Float64}}})
    ret = 0.*p[1]
    for i = 1:length(p)
        ret += fasttimes(p[i],p[i])
    end

    ret
end

function samplespectra(p::Array{IFun{Float64,Interval{Float64}}})
    n = length(p)
    r=sample(iekernel(p)/n)
    if n==1
        r
    else
        f=map(q->q[r],p)
        Q=null(f')'
        [r ;samplespectra(Q*p)]
    end
end

iekernel(p::InvariantEnsemble)=iekernel(p.basis,p.domain)
samplespectra(p::InvariantEnsemble)=samplespectra(p.basis,p.domain)

## Spectra Database

function spectradatabase(str,n::Integer,m::Colon)
  file = Pkg.dir("InvariantEnsembles/SpectraDatabase/" * str * "/" * string(n) * ".csv");

  if(filesize(file) == 0)
    []
  else
    readdlm(file,',')
  end
end

function spectradatabase(str,n::Integer,m::Integer)
    if  filesize(Pkg.dir("InvariantEnsembles/CoefficientDatabase")) == 0 ||
        filesize(Pkg.dir("InvariantEnsembles/CoefficientDatabaseUnscaled")) == 0
        error("No coefficient database found.  InvariantEnsembles package corrupted.")
    end

    dir = Pkg.dir("InvariantEnsembles/SpectraDatabase")
    if filesize(dir) == 0
        warn("Creating SpectraDatabase folder " * dir)

        mkdir(dir)
    end

    dir = Pkg.dir("InvariantEnsembles/SpectraDatabase/" * str)

    if filesize(dir) == 0
        warn("Creating folder " * dir)

        mkdir(dir)
    end

  file = dir * "/" * string(n) * ".csv"

  if(filesize(file) == 0)
    warn("No existing samples found.  Creating sample database.");

    ie = InvariantEnsemble(str,n)

    A=hcat([samplespectra(ie) for i=1:m+1]...)';
    writedlm(file,A,',');
  else
    A = readdlm(file,',');

    if ( m > size(A)[1])
      warn(string(m) * " is greater than current samples " * string(size(A)[1]) * ".  Generating more samples");

      ie = InvariantEnsemble(str,n)

      An=hcat([samplespectra(ie) for i=1:(m-size(A)[1]+1)]...)';

      A = vcat(A,An);

      writedlm(file,A,',');
    end
  end

    return A[1:m,:];
end

##Plot

function dotplot(r)
       p=Winston.FramedPlot()
       y=zeros(length(r))
       a=Winston.Points(r,y,"type","dot")
       add(p,a)
       Winston.display(p)
end

end #module