text:
function generalformat(val, precision::Integer, capitals::Bool, min_digits::Bool=false)
    if isinf(val) || isnan(val)
        return format_inf_nan(val, capitals)
    end

    if val == 0
        if min_digits
            return "0.0"
        else
            return "0"
        end
    end

    precision = max(precision, 1) #in generalformatting, precision is ≥ 1

    uintexponent = capitals ? 'E' : 'e'

    number = Ryu.writeexp(val, precision-1, false, false, false, UInt8(uintexponent))

    fractional_digits = precision-1

    exp = parse(Int, split(number, uintexponent)[2])

    exponent = ""
    if exp >= precision - (min_digits ? 1 : 0) || exp <= -5
        i = findfirst(uintexponent, number)
        number, exponent = number[1:i-1], number[i:end]
    else
        fractional_digits = max(precision-exp-1, min_digits ? 1 : 0)

        number = (capitals ? uppercase : identity)(Ryu.writefixed(val, fractional_digits))
    end

    if fractional_digits > 0
        number = rstrip(number, ['0'])
    end

    if number[end] == '.'
        if min_digits
            number *= '0'
        else
            number =  number[1:end-1]
        end
    end

    number * exponent
end

function format_inf_nan(val, capitals)
    ans = string(val) #NOTE: diferent from python where inf and nan are lowercase
    if capitals
        return uppercase(ans)
    else
        return ans
    end
end


text:
module TicTacToe

import Base:
        show

export Juego

include("Tipos.jl")
include("Interaccion.jl")
include("Tiros.jl")
include("Juego.jl")

end #module Gato

ext: jl


text:
# Generate scenarios of the demands for use within the ER-SAA framework

function generateERSAAScenarios(outputs::Array{Float64,2},inputs::Array{Float64,2},covariates_obs::Array{Float64,1},regressionMethod::String,coeff_true::Array{Float64,2})

	numDependentVar::Int64 = size(outputs,2)
	numIndependentVar::Int64 = size(inputs,2)
	numSamples::Int64 = size(outputs,1)
	demand_scen_ERSAA = zeros(Float64,numSamples,numDependentVar)

	fitQuality::Float64 = 1.0

	if(size(outputs,1) != size(inputs,1))
		throw(ErrorException("Number of output samples != number of input samples"))
	end

	if(regressionMethod == "ols")

		if(numSamples < numIndependentVar)
			throw(ErrorException("Expected number of samples > number of covariates in OLS!"))
		end

		XtX_fact = lufact((inputs')*inputs)
		XtY = (inputs')*outputs

		coeff_full = zeros(Float64,numIndependentVar,numDependentVar)
		for d = 1:numDependentVar
			coeff_full[:,d] = XtX_fact\(XtY[:,d])
		end

		demand_scen_ERSAA = repeat(((covariates_obs')*coeff_full)', outer=[1,numSamples])' + outputs - inputs*coeff_full

		fitQuality = norm(coeff_full-coeff_true,2)

	elseif(regressionMethod == "lasso")

		coeff_full = getLassoCoeff(outputs,inputs)

		demand_scen_ERSAA = repeat(((covariates_obs')*coeff_full)', outer=[1,numSamples])' + outputs - inputs*coeff_full

		fitQuality = norm(coeff_full-coeff_true,2)

	end

	return demand_scen_ERSAA, fitQuality
end

max_stars_repo_name: rohitkannan/DD-SAA

max_issues_repo_name: rohitkannan/DD-SAA

max_forks_repo_name: rohitkannan/DD-SAA


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

struct AdmissionregistrationV1Api <: SwaggerApi
    client::Swagger.Client
end

"""

create a MutatingWebhookConfiguration
Param: body::IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration
"""
function createAdmissionregistrationV1MutatingWebhookConfiguration(_api::AdmissionregistrationV1Api, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration, "/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations", ["BearerToken"], body)
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

create a ValidatingWebhookConfiguration
Param: body::IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration
"""
function createAdmissionregistrationV1ValidatingWebhookConfiguration(_api::AdmissionregistrationV1Api, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration, "/apis/admissionregistration.k8s.io/v1/validatingwebhookconfigurations", ["BearerToken"], body)
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

delete collection of MutatingWebhookConfiguration
Param: pretty::String
Param: allowWatchBookmarks::Bool
Param: body::IoK8sApimachineryPkgApisMetaV1DeleteOptions
Param: __continue__::String
Param: dryRun::String
Param: fieldSelector::String
Param: gracePeriodSeconds::Int32
Param: labelSelector::String
Param: limit::Int32
Param: orphanDependents::Bool
Param: propagationPolicy::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1Status
"""
function deleteAdmissionregistrationV1CollectionMutatingWebhookConfiguration(_api::AdmissionregistrationV1Api; pretty=nothing, allowWatchBookmarks=nothing, body=nothing, __continue__=nothing, dryRun=nothing, fieldSelector=nothing, gracePeriodSeconds=nothing, labelSelector=nothing, limit=nothing, orphanDependents=nothing, propagationPolicy=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", IoK8sApimachineryPkgApisMetaV1Status, "/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations", ["BearerToken"], body)
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "gracePeriodSeconds", gracePeriodSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "orphanDependents", orphanDependents)  # type Bool
    Swagger.set_param(_ctx.query, "propagationPolicy", propagationPolicy)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

delete collection of ValidatingWebhookConfiguration
Param: pretty::String
Param: allowWatchBookmarks::Bool
Param: body::IoK8sApimachineryPkgApisMetaV1DeleteOptions
Param: __continue__::String
Param: dryRun::String
Param: fieldSelector::String
Param: gracePeriodSeconds::Int32
Param: labelSelector::String
Param: limit::Int32
Param: orphanDependents::Bool
Param: propagationPolicy::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1Status
"""
function deleteAdmissionregistrationV1CollectionValidatingWebhookConfiguration(_api::AdmissionregistrationV1Api; pretty=nothing, allowWatchBookmarks=nothing, body=nothing, __continue__=nothing, dryRun=nothing, fieldSelector=nothing, gracePeriodSeconds=nothing, labelSelector=nothing, limit=nothing, orphanDependents=nothing, propagationPolicy=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", IoK8sApimachineryPkgApisMetaV1Status, "/apis/admissionregistration.k8s.io/v1/validatingwebhookconfigurations", ["BearerToken"], body)
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "gracePeriodSeconds", gracePeriodSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "orphanDependents", orphanDependents)  # type Bool
    Swagger.set_param(_ctx.query, "propagationPolicy", propagationPolicy)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

delete a MutatingWebhookConfiguration
Param: name::String (required)
Param: pretty::String
Param: body::IoK8sApimachineryPkgApisMetaV1DeleteOptions
Param: dryRun::String
Param: gracePeriodSeconds::Int32
Param: orphanDependents::Bool
Param: propagationPolicy::String
Return: IoK8sApimachineryPkgApisMetaV1Status
"""
function deleteAdmissionregistrationV1MutatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String; pretty=nothing, body=nothing, dryRun=nothing, gracePeriodSeconds=nothing, orphanDependents=nothing, propagationPolicy=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", IoK8sApimachineryPkgApisMetaV1Status, "/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "gracePeriodSeconds", gracePeriodSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "orphanDependents", orphanDependents)  # type Bool
    Swagger.set_param(_ctx.query, "propagationPolicy", propagationPolicy)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

delete a ValidatingWebhookConfiguration
Param: name::String (required)
Param: pretty::String
Param: body::IoK8sApimachineryPkgApisMetaV1DeleteOptions
Param: dryRun::String
Param: gracePeriodSeconds::Int32
Param: orphanDependents::Bool
Param: propagationPolicy::String
Return: IoK8sApimachineryPkgApisMetaV1Status
"""
function deleteAdmissionregistrationV1ValidatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String; pretty=nothing, body=nothing, dryRun=nothing, gracePeriodSeconds=nothing, orphanDependents=nothing, propagationPolicy=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", IoK8sApimachineryPkgApisMetaV1Status, "/apis/admissionregistration.k8s.io/v1/validatingwebhookconfigurations/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "gracePeriodSeconds", gracePeriodSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "orphanDependents", orphanDependents)  # type Bool
    Swagger.set_param(_ctx.query, "propagationPolicy", propagationPolicy)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

get available resources
Return: IoK8sApimachineryPkgApisMetaV1APIResourceList
"""
function getAdmissionregistrationV1APIResources(_api::AdmissionregistrationV1Api; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1APIResourceList, "/apis/admissionregistration.k8s.io/v1/", ["BearerToken"])
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

list or watch objects of kind MutatingWebhookConfiguration
Param: pretty::String
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApiAdmissionregistrationV1MutatingWebhookConfigurationList
"""
function listAdmissionregistrationV1MutatingWebhookConfiguration(_api::AdmissionregistrationV1Api; pretty=nothing, allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAdmissionregistrationV1MutatingWebhookConfigurationList, "/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations", ["BearerToken"])
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

list or watch objects of kind ValidatingWebhookConfiguration
Param: pretty::String
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApiAdmissionregistrationV1ValidatingWebhookConfigurationList
"""
function listAdmissionregistrationV1ValidatingWebhookConfiguration(_api::AdmissionregistrationV1Api; pretty=nothing, allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAdmissionregistrationV1ValidatingWebhookConfigurationList, "/apis/admissionregistration.k8s.io/v1/validatingwebhookconfigurations", ["BearerToken"])
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

partially update the specified MutatingWebhookConfiguration
Param: name::String (required)
Param: body::IoK8sApimachineryPkgApisMetaV1Patch (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Param: force::Bool
Return: IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration
"""
function patchAdmissionregistrationV1MutatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration, "/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_param(_ctx.query, "force", force)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json-patch+json", "application/merge-patch+json", "application/strategic-merge-patch+json", "application/apply-patch+yaml"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

partially update the specified ValidatingWebhookConfiguration
Param: name::String (required)
Param: body::IoK8sApimachineryPkgApisMetaV1Patch (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Param: force::Bool
Return: IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration
"""
function patchAdmissionregistrationV1ValidatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, force=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PATCH", IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration, "/apis/admissionregistration.k8s.io/v1/validatingwebhookconfigurations/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_param(_ctx.query, "force", force)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json-patch+json", "application/merge-patch+json", "application/strategic-merge-patch+json", "application/apply-patch+yaml"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

read the specified MutatingWebhookConfiguration
Param: name::String (required)
Param: pretty::String
Param: exact::Bool
Param: __export__::Bool
Return: IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration
"""
function readAdmissionregistrationV1MutatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String; pretty=nothing, exact=nothing, __export__=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration, "/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations/{name}", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "exact", exact)  # type Bool
    Swagger.set_param(_ctx.query, "export", __export__)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

read the specified ValidatingWebhookConfiguration
Param: name::String (required)
Param: pretty::String
Param: exact::Bool
Param: __export__::Bool
Return: IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration
"""
function readAdmissionregistrationV1ValidatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String; pretty=nothing, exact=nothing, __export__=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration, "/apis/admissionregistration.k8s.io/v1/validatingwebhookconfigurations/{name}", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "exact", exact)  # type Bool
    Swagger.set_param(_ctx.query, "export", __export__)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

replace the specified MutatingWebhookConfiguration
Param: name::String (required)
Param: body::IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration
"""
function replaceAdmissionregistrationV1MutatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", IoK8sApiAdmissionregistrationV1MutatingWebhookConfiguration, "/apis/admissionregistration.k8s.io/v1/mutatingwebhookconfigurations/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

replace the specified ValidatingWebhookConfiguration
Param: name::String (required)
Param: body::IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration (required)
Param: pretty::String
Param: dryRun::String
Param: fieldManager::String
Return: IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration
"""
function replaceAdmissionregistrationV1ValidatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String, body; pretty=nothing, dryRun=nothing, fieldManager=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", IoK8sApiAdmissionregistrationV1ValidatingWebhookConfiguration, "/apis/admissionregistration.k8s.io/v1/validatingwebhookconfigurations/{name}", ["BearerToken"], body)
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "dryRun", dryRun)  # type String
    Swagger.set_param(_ctx.query, "fieldManager", fieldManager)  # type String
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

watch changes to an object of kind MutatingWebhookConfiguration. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.
Param: name::String (required)
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAdmissionregistrationV1MutatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/admissionregistration.k8s.io/v1/watch/mutatingwebhookconfigurations/{name}", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

watch individual changes to a list of MutatingWebhookConfiguration. deprecated: use the 'watch' parameter with a list operation instead.
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAdmissionregistrationV1MutatingWebhookConfigurationList(_api::AdmissionregistrationV1Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/admissionregistration.k8s.io/v1/watch/mutatingwebhookconfigurations", ["BearerToken"])
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

watch changes to an object of kind ValidatingWebhookConfiguration. deprecated: use the 'watch' parameter with a list operation instead, filtered to a single item with the 'fieldSelector' parameter.
Param: name::String (required)
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAdmissionregistrationV1ValidatingWebhookConfiguration(_api::AdmissionregistrationV1Api, name::String; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/admissionregistration.k8s.io/v1/watch/validatingwebhookconfigurations/{name}", ["BearerToken"])
    Swagger.set_param(_ctx.path, "name", name)  # type String
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

"""

watch individual changes to a list of ValidatingWebhookConfiguration. deprecated: use the 'watch' parameter with a list operation instead.
Param: allowWatchBookmarks::Bool
Param: __continue__::String
Param: fieldSelector::String
Param: labelSelector::String
Param: limit::Int32
Param: pretty::String
Param: resourceVersion::String
Param: timeoutSeconds::Int32
Param: watch::Bool
Return: IoK8sApimachineryPkgApisMetaV1WatchEvent
"""
function watchAdmissionregistrationV1ValidatingWebhookConfigurationList(_api::AdmissionregistrationV1Api; allowWatchBookmarks=nothing, __continue__=nothing, fieldSelector=nothing, labelSelector=nothing, limit=nothing, pretty=nothing, resourceVersion=nothing, timeoutSeconds=nothing, watch=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", IoK8sApimachineryPkgApisMetaV1WatchEvent, "/apis/admissionregistration.k8s.io/v1/watch/validatingwebhookconfigurations", ["BearerToken"])
    Swagger.set_param(_ctx.query, "allowWatchBookmarks", allowWatchBookmarks)  # type Bool
    Swagger.set_param(_ctx.query, "continue", __continue__)  # type String
    Swagger.set_param(_ctx.query, "fieldSelector", fieldSelector)  # type String
    Swagger.set_param(_ctx.query, "labelSelector", labelSelector)  # type String
    Swagger.set_param(_ctx.query, "limit", limit)  # type Int32
    Swagger.set_param(_ctx.query, "pretty", pretty)  # type String
    Swagger.set_param(_ctx.query, "resourceVersion", resourceVersion)  # type String
    Swagger.set_param(_ctx.query, "timeoutSeconds", timeoutSeconds)  # type Int32
    Swagger.set_param(_ctx.query, "watch", watch)  # type Bool
    Swagger.set_header_accept(_ctx, ["application/json", "application/yaml", "application/vnd.kubernetes.protobuf", "application/json;stream=watch", "application/vnd.kubernetes.protobuf;stream=watch"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["*/*"] : [_mediaType])
    Swagger.exec(_ctx)
end

export createAdmissionregistrationV1MutatingWebhookConfiguration, createAdmissionregistrationV1ValidatingWebhookConfiguration, deleteAdmissionregistrationV1CollectionMutatingWebhookConfiguration, deleteAdmissionregistrationV1CollectionValidatingWebhookConfiguration, deleteAdmissionregistrationV1MutatingWebhookConfiguration, deleteAdmissionregistrationV1ValidatingWebhookConfiguration, getAdmissionregistrationV1APIResources, listAdmissionregistrationV1MutatingWebhookConfiguration, listAdmissionregistrationV1ValidatingWebhookConfiguration, patchAdmissionregistrationV1MutatingWebhookConfiguration, patchAdmissionregistrationV1ValidatingWebhookConfiguration, readAdmissionregistrationV1MutatingWebhookConfiguration, readAdmissionregistrationV1ValidatingWebhookConfiguration, replaceAdmissionregistrationV1MutatingWebhookConfiguration, replaceAdmissionregistrationV1ValidatingWebhookConfiguration, watchAdmissionregistrationV1MutatingWebhookConfiguration, watchAdmissionregistrationV1MutatingWebhookConfigurationList, watchAdmissionregistrationV1ValidatingWebhookConfiguration, watchAdmissionregistrationV1ValidatingWebhookConfigurationList


text:
using JLD2
using Flux
using FileIO

# OUTPUT_PATH = joinpath(pwd(), "Output")
OUTPUT_PATH = joinpath("D:\\University Matters\\Massachusetts Institute of Technology\\CLiMA Project\\OceanParameterizations.jl\\training_output")

train_files = ["-7.5e-4", "-2.5e-4"]
train_epochs = [100 for i in 1:2]
train_tranges = [1:5:10, 1:5:100]
opts = [[ADAM(), Descent(0.01)], [ADAM()]]
nums = [1, 2]

N_inputs = 96
hidden_units = 400
N_outputs = 31
uw_NN = Chain(Dense(N_inputs, hidden_units, relu), Dense(hidden_units, hidden_units, relu), Dense(hidden_units, N_outputs))
vw_NN = Chain(Dense(N_inputs, hidden_units, relu), Dense(hidden_units, hidden_units, relu), Dense(hidden_units, N_outputs))
wT_NN = Chain(Dense(N_inputs, hidden_units, relu), Dense(hidden_units, hidden_units, relu), Dense(hidden_units, N_outputs))

FILE_PATH = joinpath(OUTPUT_PATH, "example.jld2")

function write_metadata_NDE_training(FILE_PATH, train_files, train_epochs, train_tranges, opts, uw_NN, vw_NN, wT_NN)
    jldopen(FILE_PATH, "w") do file
        training_info = JLD2.Group(file, "training_info")
        training_info["train_files"] = train_files
        training_info["train_epochs"] = train_epochs
        training_info["train_tranges"] = train_tranges
        training_info["optimizers"] = opts
        training_info["uw_neural_network"] = uw_NN
        training_info["vw_neural_network"] = vw_NN
        training_info["wT_neural_network"] = wT_NN
    end
end

write_metadata_NDE_training(FILE_PATH, train_files, train_epochs, train_tranges, opts, uw_NN, vw_NN, wT_NN)

function write_data_NDE_training(FILE_PATH, loss, uw_NN, vw_NN, wT_NN, stage, epoch)
    jldopen(FILE_PATH, "a") do file
        file["training_data/loss/$stage/$epoch"] = loss
        file["training_data/neural_network/uw/$stage/$epoch"] = uw_NN
        file["training_data/neural_network/vw/$stage/$epoch"] = vw_NN
        file["training_data/neural_network/wT/$stage/$epoch"] = wT_NN
    end
end

for i in 1:length(train_epochs), j in 1:train_epochs[i]
    write_data_NDE_training(FILE_PATH, 1e-3, uw_NN, vw_NN, wT_NN, i, j)
end

function write_metadata_NN_training(FILE_PATH, train_files, train_epochs, opts, uw_NN, vw_NN, wT_NN)
    jldopen(FILE_PATH, "w") do file
        training_info = JLD2.Group(file, "training_info")
        training_info["train_files"] = train_files
        training_info["train_epochs"] = train_epochs
        training_info["optimizers"] = opts
        training_info["uw_neural_network"] = uw_NN
        training_info["vw_neural_network"] = vw_NN
        training_info["wT_neural_network"] = wT_NN
    end
end

function write_data_NN_training(FILE_PATH, loss, uw_NN, vw_NN, wT_NN, stage, epoch)
    jldopen(FILE_PATH, "a") do file
        file["training_data/loss/$stage/$epoch"] = loss
        file["training_data/neural_network/uw/$stage/$epoch"] = uw_NN
        file["training_data/neural_network/vw/$stage/$epoch"] = vw_NN
        file["training_data/neural_network/wT/$stage/$epoch"] = wT_NN
    end
end


text:
module JDF

using Blosc: Blosc
using Missings: Missings
using BufferedStreams
#using RLEVectors
using WeakRefStrings, TimeZones

using StatsBase: rle, inverse_rle, countmap, sample

import Base: show, getindex, setindex!, eltype, names

using Base: size

using Serialization: serialize, deserialize

import Base.Threads: @spawn

function __init__()
    Blosc.set_num_threads(Threads.nthreads())
end

export savejdf, loadjdf
export column_loader, column_loader!
export type_compress!, type_compress
export compress_then_write
export JDFFile, @jdf_str, jdfmetadata, metadata, size, names
export IsBitsType, eachcol, some_elm, getindex, istable

include("JDFFile.jl")
include("type-writer-loader/Bool.jl")
include("type-writer-loader/Char.jl")
include("type-writer-loader/DateTime.jl")
include("type-writer-loader/categorical-arrays.jl")
include("type-writer-loader/pooled-arrays.jl")
include("type-writer-loader/Missing.jl")
include("type-writer-loader/Nothing.jl")
include("type-writer-loader/String.jl")
include("type-writer-loader/StringArray.jl")
include("type-writer-loader/Symbol.jl")
include("type-writer-loader/ZonedDateTime.jl")
include("type-writer-loader/substring.jl")

include("column_loader.jl")
include("compress_then_write.jl")

include("load-columns.jl")
include("loadjdf.jl")
include("savejdf.jl")
include("type_compress.jl")

include("metadata.jl")
include("eachcol.jl")
include("Tables.jl")

end # module

max_stars_repo_name: xiaodaigh/JDF

max_issues_repo_name: xiaodaigh/JDF

max_forks_repo_name: xiaodaigh/JDF


text:
import Base.timedwait
import Base.isapprox
import PrettyPrint

using Test
using Scruff
using Scruff.Utils
using Scruff.RTUtils
using Scruff.SFuncs
using Scruff.Algorithms
import Scruff.Operators: cpdf

@testset "Importance" begin

    @testset "Sampling utilities" begin
        @testset "Probability" begin
            sample1 = Dict(:a => 1, :b => 2)
            sample2 = Dict(:a => 1, :b => 3)
            sample3 = Dict(:a => 2, :b => 4)
            lws = [-0.1, -0.2, -0.3]
            parts = Particles([sample1, sample2, sample3], lws)
            tot = sum([exp(x) for x in lws])
            p1 = exp(-0.1) + exp(-0.2)
            @test isapprox(probability(parts, s -> s[:a] == 1), p1 / tot)
        end

        @testset "Marginal" begin
            sample1 = Dict(:a => 1, :b => 2)
            sample2 = Dict(:a => 1, :b => 3)
            sample3 = Dict(:a => 2, :b => 4)
            lws = [-0.1, -0.2, -0.3]
            parts = Particles([sample1, sample2, sample3], lws)
            p1 = exp(-0.1) + exp(-0.2)
            p2 = exp(-0.3)
            tot = p1 + p2
            marg = marginal(parts, :a)
            @test isapprox(cpdf(marg, (), 1), p1 / tot)
            @test isapprox(cpdf(marg, (), 2), p2 / tot)
        end

        @testset "Effective sample size" begin
            @test isapprox(effective_sample_size([log(0.4)]), 1.0)
            @test isapprox(effective_sample_size([log(0.4), log(0.2)]), (0.6 * 0.6 / (0.4 * 0.4 + 0.2 * 0.2)))
        end

        @testset "Normalizing weights" begin
            @test isapprox(normalize_weights([log(0.1), log(0.3)]), [log(0.25), log(0.75)])
        end

        @testset "Probability of evidence" begin
            @test isapprox(log_prob_evidence([log(0.1), log(0.3)]), log((0.1+0.3)/2))
        end

        @testset "Resampling" begin
            samples = fill(Dict(:a => false), 1000)
            append!(samples, fill(Dict(:a => true), 1000))
            weights = fill(log(0.1), 1000)
            append!(weights, fill(log(0.9), 1000))
            ps = resample(Particles(samples, weights))
            @test all(x -> x == 0.0, ps.log_weights)
            @test isapprox(count(x -> x[:a], ps.samples) / 2000, 0.9, atol = 0.05)
        end
    end

    @testset "Rejection" begin

        @testset "Basic" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = Rejection(1000)
            infer(alg, runtime)
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i1, x -> x == :a), 0.1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, x -> x == :b), 0.9; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, x -> x == 1),
                0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, x -> x == 2),
                0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), 0.1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), 0.9; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
        end

        @testset "With placeholder" begin
            p1 = Placeholder{Symbol}(:p1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v2], VariableGraph(v2 => [p1]), Placeholder[p1])
            runtime = Runtime(net)
            default_initializer(runtime, 10, Dict(p1.name => Cat([:a,:b], [0.1, 0.9])))
            alg = Rejection(1000)
            infer(alg, runtime)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i2, 1),
                0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2),
                0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m2, (), 1), 0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(cpdf(m2, (), 2), 0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
        end

        @testset "With hard evidence" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = Rejection(1000)
            infer(alg, runtime, Dict{Symbol, Score}(:v2 => HardScore(2)))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            p1 = 0.1 * 0.8
            p2 = 0.9 * 0.7
            z = p1 + p2
            @test isapprox(probability(alg, runtime, i1, :a), p1 / z; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), p2 / z; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), 0.0; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), 1.0; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), p1 / z; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), p2 / z; atol = 0.05)
            @test isapprox(cpdf(m2, (), 1), 0.0; atol = 0.05)
            @test isapprox(cpdf(m2, (), 2), 1.0; atol = 0.05)
        end

        @testset "With soft evidence" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = Rejection(1000)
            infer(alg, runtime, Dict{Symbol, Score}(:v2 => SoftScore(Dict(1 => 0.6, 2 => 0.4))))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            pa = 0.1 * (0.2 * 0.6 + 0.8 * 0.4)
            pb = 0.9 * (0.3 * 0.6 + 0.7 * 0.4)
            z1 = pa + pb
            # soft evidence is treated like a lambda message on a variable,
            # so the prior also comes into play, unlike an intervention
            p1 = (0.1 * 0.2 + 0.9 * 0.3) * 0.6
            p2 = (0.1 * 0.8 + 0.9 * 0.7) * 0.4
            z2 = p1 + p2
            @assert isapprox(z1, z2)
            @test isapprox(probability(alg, runtime, i1, :a), pa / z1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), pb / z1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), p1 / z2; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), p2 / z2; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), pa / z1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), pb / z1; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), p1 / z2; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), p2 / z2; atol = 0.05)
        end

        @testset "With intervention" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = Rejection(1000)
            infer(alg, runtime, Dict{Symbol, Score}(), Dict{Symbol, Dist}(:v2 => Constant(2)))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i1, :a), 0.1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), 0.9; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), 0.0; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), 1.0; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), 0.1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), 0.9; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.0; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 1.0; atol = 0.05)
        end

    end

    @testset "LW" begin
        @testset "Basic" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = LW(1000)
            infer(alg, runtime)
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i1, x -> x == :a), 0.1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, x -> x == :b), 0.9; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, x -> x == 1),
                0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, x -> x == 2),
                0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), 0.1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), 0.9; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
        end

        @testset "With placeholder" begin
            p1 = Placeholder{Symbol}(:p1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v2], VariableGraph(v2 => [p1]), Placeholder[p1])
            runtime = Runtime(net)
            default_initializer(runtime, 10, Dict(p1.name => Cat([:a,:b], [0.1, 0.9])))
            alg = LW(1000)
            infer(alg, runtime)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i2, 1),
                0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2),
                0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m2, (), 1), 0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(cpdf(m2, (), 2), 0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
        end

        @testset "With hard evidence" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = LW(1000)
            infer(alg, runtime, Dict{Symbol, Score}(:v2 => HardScore(2)))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            p1 = 0.1 * 0.8
            p2 = 0.9 * 0.7
            z = p1 + p2
            @test isapprox(probability(alg, runtime, i1, :a), p1 / z; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), p2 / z; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), 0.0; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), 1.0; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), p1 / z; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), p2 / z; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.0; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 1.0; atol = 0.05)
        end

        @testset "With soft evidence" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = LW(1000)
            infer(alg, runtime, Dict{Symbol, Score}(:v2 => SoftScore(Dict(1 => 0.6, 2 => 0.4))))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            pa = 0.1 * (0.2 * 0.6 + 0.8 * 0.4)
            pb = 0.9 * (0.3 * 0.6 + 0.7 * 0.4)
            z1 = pa + pb
            # soft evidence is treated like a lambda message on a variable,
            # so the prior also comes into play, unlike an intervention
            p1 = (0.1 * 0.2 + 0.9 * 0.3) * 0.6
            p2 = (0.1 * 0.8 + 0.9 * 0.7) * 0.4
            z2 = p1 + p2
            @assert isapprox(z1, z2)
            @test isapprox(probability(alg, runtime, i1, :a), pa / z1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), pb / z1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), p1 / z2; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), p2 / z2; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), pa / z1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), pb / z1; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), p1 / z2; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), p2 / z2; atol = 0.05)
        end

        @testset "With intervention" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = LW(1000)
            infer(alg, runtime, Dict{Symbol, Score}(), Dict{Symbol, Dist}(:v2 => Constant(2)))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i1, :a), 0.1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), 0.9; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), 0.0; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), 1.0; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), 0.1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), 0.9; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.0; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 1.0; atol = 0.05)
        end
    end

    @testset "Custom proposal" begin
        prop::Dict{Symbol,SFunc} = Dict(:v2 =>
                    DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7])))
        alg = Importance(make_custom_proposal(prop), 1000)

        @testset "Basic" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            infer(alg, runtime)
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i1, x -> x == :a), 0.1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, x -> x == :b), 0.9; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, x -> x == 1),
                0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, x -> x == 2),
                0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), 0.1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), 0.9; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
        end

        @testset "With placeholder" begin
            p1 = Placeholder{Symbol}(:p1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v2], VariableGraph(v2 => [p1]), Placeholder[p1])
            runtime = Runtime(net)
            default_initializer(runtime, 10, Dict(p1.name => Cat([:a,:b], [0.1, 0.9])))
            infer(alg, runtime)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i2, 1),
                0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2),
                0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m2, (), 1), 0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(cpdf(m2, (), 2), 0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
        end

        @testset "With hard evidence" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            infer(alg, runtime, Dict{Symbol, Score}(:v2 => HardScore(2)))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            p1 = 0.1 * 0.8
            p2 = 0.9 * 0.7
            z = p1 + p2
            @test isapprox(probability(alg, runtime, i1, :a), p1 / z; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), p2 / z; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), 0.0; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), 1.0; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), p1 / z; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), p2 / z; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.0; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 1.0; atol = 0.05)
        end

        @testset "With soft evidence" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            infer(alg, runtime, Dict{Symbol, Score}(:v2 => SoftScore(Dict(1 => 0.6, 2 => 0.4))))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            pa = 0.1 * (0.2 * 0.6 + 0.8 * 0.4)
            pb = 0.9 * (0.3 * 0.6 + 0.7 * 0.4)
            z1 = pa + pb
            # soft evidence is treated like a lambda message on a variable,
            # so the prior also comes into play, unlike an intervention
            p1 = (0.1 * 0.2 + 0.9 * 0.3) * 0.6
            p2 = (0.1 * 0.8 + 0.9 * 0.7) * 0.4
            z2 = p1 + p2
            @assert isapprox(z1, z2)
            @test isapprox(probability(alg, runtime, i1, :a), pa / z1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), pb / z1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), p1 / z2; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), p2 / z2; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), pa / z1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), pb / z1; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), p1 / z2; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), p2 / z2; atol = 0.05)
        end

        @testset "With intervention" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            infer(alg, runtime, Dict{Symbol, Score}(), Dict{Symbol, Dist}(:v2 => Constant(2)))
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i1, :a), 0.1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), 0.9; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), 0.0; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), 1.0; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), 0.1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), 0.9; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.0; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 1.0; atol = 0.05)
        end
    end

    @testset "Iterative sampling" begin

        @testset "Basic" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = IterativeSampler(LW(1000))
            prepare(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 0
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 1000
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 2000
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i1, x -> x == :a), 0.1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, x -> x == :b), 0.9; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, x -> x == 1),
                0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, x -> x == 2),
                0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), 0.1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), 0.9; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
        end

        @testset "With placeholder" begin
            p1 = Placeholder{Symbol}(:p1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v2], VariableGraph(v2 => [p1]), Placeholder[p1])
            runtime = Runtime(net)
            default_initializer(runtime, 10, Dict(p1.name => Cat([:a,:b], [0.1, 0.9])))
            alg = IterativeSampler(LW(1000))
            prepare(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 0
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 1000
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 2000
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i2, 1),
                0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2),
                0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m2, (), 1), 0.1 * 0.2 + 0.9 * 0.3; atol = 0.05)
            @test isapprox(cpdf(m2, (), 2), 0.1 * 0.8 + 0.9 * 0.7; atol = 0.05)
        end

        @testset "With hard evidence" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = IterativeSampler(LW(1000))
            prepare(alg, runtime, Dict(:v2 => HardScore(2)))
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 0
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 1000
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 2000
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            p1 = 0.1 * 0.8
            p2 = 0.9 * 0.7
            z = p1 + p2
            @test isapprox(probability(alg, runtime, i1, :a), p1 / z; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), p2 / z; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), 0.0; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), 1.0; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), p1 / z; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), p2 / z; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.0; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 1.0; atol = 0.05)
        end

        @testset "With soft evidence" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = IterativeSampler(LW(1000))
            prepare(alg, runtime, Dict(:v2 => SoftScore(Dict(1 => 0.6, 2 => 0.4))))
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 0
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 1000
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 2000
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            pa = 0.1 * (0.2 * 0.6 + 0.8 * 0.4)
            pb = 0.9 * (0.3 * 0.6 + 0.7 * 0.4)
            z1 = pa + pb
            # soft evidence is treated like a lambda message on a variable,
            # so the prior also comes into play, unlike an intervention
            p1 = (0.1 * 0.2 + 0.9 * 0.3) * 0.6
            p2 = (0.1 * 0.8 + 0.9 * 0.7) * 0.4
            z2 = p1 + p2
            @assert isapprox(z1, z2)
            @test isapprox(probability(alg, runtime, i1, :a), pa / z1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), pb / z1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), p1 / z2; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), p2 / z2; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), pa / z1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), pb / z1; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), p1 / z2; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), p2 / z2; atol = 0.05)
        end

        @testset "With intervention" begin
            v1 = Cat([:a,:b], [0.1, 0.9])()(:v1)
            v2 = DiscreteCPT([1,2], Dict((:a,) => [0.2, 0.8], (:b,) => [0.3, 0.7]))()(:v2)
            net = InstantNetwork(Variable[v1,v2], VariableGraph(v2 => [v1]))
            runtime = Runtime(net)
            default_initializer(runtime)
            alg = IterativeSampler(LW(1000))
            prepare(alg, runtime, Dict{Symbol, Score}(), Dict(:v2 => Constant(2)))
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 0
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 1000
            refine(alg, runtime)
            particles = get_state(runtime, :particles)
            @test length(particles.samples) == 2000
            i1 = current_instance(runtime, v1)
            i2 = current_instance(runtime, v2)
            @test isapprox(probability(alg, runtime, i1, :a), 0.1; atol = 0.05)
            @test isapprox(probability(alg, runtime, i1, :b), 0.9; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 1), 0.0; atol = 0.05)
            @test isapprox(probability(alg, runtime, i2, 2), 1.0; atol = 0.05)
            m1 = marginal(alg, runtime, i1)
            m2 = marginal(alg, runtime, i2)
            @test isapprox(cpdf(m1, (), :a), 0.1; atol = 0.05)
            @test isapprox(cpdf(m1, (), :b), 0.9; atol = 0.05)
            @test isapprox(cpdf(m2, (), :1), 0.0; atol = 0.05)
            @test isapprox(cpdf(m2, (), :2), 1.0; atol = 0.05)
        end

    end

end


text:
module SPPL

# A wrapper package (using `PythonCall.jl`) to `sppl`.

using MacroTools
using MacroTools: @capture, rmlines, unblock
using PythonCall

const fractions = PythonCall.pynew()
const sppl = PythonCall.pynew()
const dists = PythonCall.pynew()
const ast_compiler = PythonCall.pynew()
const sppl_compiler = PythonCall.pynew()
const transforms = PythonCall.pynew()
const sym_util = PythonCall.pynew()
const dnf = PythonCall.pynew()
const compiler = PythonCall.pynew()
const Id = PythonCall.pynew()
const IdArray = PythonCall.pynew()
const Skip = PythonCall.pynew()
const Sample = PythonCall.pynew()
const Transform = PythonCall.pynew()
const Cond = PythonCall.pynew()
const IfElse = PythonCall.pynew()
const For = PythonCall.pynew()
const SSwitch = PythonCall.pynew()
const Sequence = PythonCall.pynew()
const dnf_to_disjoint_union = PythonCall.pynew()
const binspace = PythonCall.pynew()
const Fraction = PythonCall.pynew()
const Sqrt = PythonCall.pynew()

function __init__()
    PythonCall.pycopy!(fractions, pyimport("fractions"))
    PythonCall.pycopy!(sppl, pyimport("sppl"))
    PythonCall.pycopy!(dists, pyimport("sppl.distributions"))
    PythonCall.pycopy!(ast_compiler,
                       pyimport("sppl.compilers.ast_to_spe"))
    PythonCall.pycopy!(sppl_compiler,
                       pyimport("sppl.compilers.sppl_to_python"))
    PythonCall.pycopy!(transforms, pyimport("sppl.transforms"))
    PythonCall.pycopy!(sym_util, pyimport("sppl.sym_util"))
    PythonCall.pycopy!(dnf, pyimport("sppl.dnf"))
    PythonCall.pycopy!(compiler, sppl_compiler.SPPL_Compiler)
    PythonCall.pycopy!(Id, ast_compiler.Id)
    PythonCall.pycopy!(IdArray, ast_compiler.IdArray)
    PythonCall.pycopy!(Skip, ast_compiler.Skip)
    PythonCall.pycopy!(Sample, ast_compiler.Sample)
    PythonCall.pycopy!(Transform, ast_compiler.Transform)
    PythonCall.pycopy!(Cond, ast_compiler.Condition)
    PythonCall.pycopy!(IfElse, ast_compiler.IfElse)
    PythonCall.pycopy!(For, ast_compiler.For)
    PythonCall.pycopy!(SSwitch, ast_compiler.Switch)
    PythonCall.pycopy!(Sequence, ast_compiler.Sequence)
    PythonCall.pycopy!(dnf_to_disjoint_union, dnf.dnf_to_disjoint_union)
    PythonCall.pycopy!(binspace, sym_util.binspace)
    PythonCall.pycopy!(Fraction, fractions.Fraction)
    PythonCall.pycopy!(Sqrt, transforms.Sqrt)
end

export fractions, sppl, dists, ast_compiler, sppl_compiler, transforms, sym_util, dnf, compiler
export Id, IdArray, Skip, Sample, Transform, Cond, IfElse, For, Switch, Sequence

function Switch(fn::Function, y, enumeration)
    return SSwitch(y, enumeration, fn)
end

const array = IdArray
export array

set(s::Symbol) = pyset([string(s)])
set(s) = pyset([s]); export set

export dnf_to_disjoint_union
export binspace, Fraction, Sqrt

#####
##### Distributions
#####

Atomic(loc) = dists.atomic(loc = loc)
Choice(d) = dists.NominalDistribution(pydict(d))
Choice(d::Vector) = dists.NominalDistribution(pydict(d))
function Choice(d::Vector{Pair{Symbol, T}}) where T
    d = map(d) do (k, v)
        (string(k), v)
    end
    dists.NominalDistribution(pydict(d))
end
Uniform(loc, scale) = dists.uniform(loc = loc, scale = scale)
Bernoulli(p) = dists.bernoulli(p = p)
Poisson(μ) = dists.poisson(mu = μ)
TruncatedNormal(a, b) = dists.truncnorm(a = a, b = b)
Normal(loc, scale) = dists.norm(loc = loc, scale = scale)
Normal() = dists.norm()
Binomial(n, p) = dists.binomial(n = n, p = p)
DiscreteUniform(values) = dists.uniformd(values = values)
RandInt(low, high) = dists.randint(low = low, high = high)
Beta(a, b) = dists.beta(a = a, b = b)
DiscreteLaplace(loc, a) = dists.dlaplace(loc = loc, a = a)
Gamma(loc, a) = dists.gamma(loc = loc, a = a)

export Atomic
export Choice
export Uniform
export Bernoulli
export Poisson
export TruncatedNormal
export Normal
export Binomial
export DiscreteUniform
export RandInt
export Beta
export DiscreteLaplace
export Gamma

#####
##### Accessor utility calls
#####

mutual_information(model::Py, cond1::Py, cond2::Py) = model.mutual_information(cond1, cond2)
condition(model::Py, cond::Py) = model.condition(cond)
probability(model::Py, cond::Py) = model.prob(cond)

export condition, probability, mutual_information

#####
##### Macros
#####

function id(x::Symbol)
    return Id(string(x))
end

function parse_block(expr::Expr)
    commands = Any[]
    array_declarations = Any[]
    variable_declarations = Dict()
    namespace = Any[]
    for ex in expr.args
        new = MacroTools.postwalk(ex) do e

            if @capture(e, v_[a_] ~ d_)
                !(v in keys(variable_declarations)) && error("ParseError (parse_block): IdArray must be declared before use.")
                e = Expr(:call, GlobalRef(SPPL, :Sample),
                         quote $v[$a] end, d)

            elseif @capture(e, v_ ~ d_)
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :id), QuoteNode(v)))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :id), QuoteNode(v))))
                end
                e = Expr(:call, GlobalRef(SPPL, :Sample), v, d)

            elseif @capture(e, v_ = array(n_))
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :IdArray), QuoteNode(v), n))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :IdArray), QuoteNode(v), n)))
                end
                e = Expr(:noop)

            elseif @capture(e, v_[a_] .> d_)
                !(v in keys(variable_declarations)) && error("ParseError (parse_block): IdArray must be declared before use.")
                e = Expr(:call, GlobalRef(SPPL, :Transform), quote $v[$a] end, d)

            elseif @capture(e, v_ .> d_)
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :id), QuoteNode(v)))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :id), QuoteNode(v))))
                end
                e = Expr(:call, GlobalRef(SPPL, :Transform), v, d)

            elseif @capture(e, v_ == d_)
                Expr(:call, :(<<), v, Expr(:call, GlobalRef(SPPL, :set), d))

            elseif @capture(e, if cond_ body1__ else body2__ end)
                Expr(:call, GlobalRef(SPPL, :IfElse), cond,
                     length(body1) == 1 ? body1[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body1...),
                     true,
                     length(body2) == 1 ? body2[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body2...))

            elseif @capture(e, for ind_ in stx_ : endx_ body_ end)
                # Note: the endx + 1 gives for loops Julia bound inclusion semantics.
                Expr(:call, GlobalRef(SPPL, :For),
                     stx,
                     Expr(:call, +, endx, 1),
                     Expr(:->, ind, body))

            elseif @capture(e, cond_ ? body1__ : body2__)
                Expr(:call, GlobalRef(SPPL, :IfElse), cond,
                     length(body1) == 1 ? body1[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body1...),
                     true,
                     length(body2) == 1 ? body2[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body2...))

            else
                e

            end
        end
        push!(commands, new)
    end

    # Filter commands to remove :noop expressions caused by array declarations exprs (see this part of the conditional matching above).
    commands = filter(commands) do expr
        expr isa Expr && expr.head != :noop
    end

    # Organize body into a Sequence - return a namespace.
    emit = Expr(:block, values(variable_declarations)...,
                Expr(:(=), :command, Expr(:call, GlobalRef(SPPL, :Sequence), commands...)),
                quote model = command.interpret() end,
                Expr(:(=), :namespace, Expr(:tuple, namespace..., Expr(:(=), :model, :model))),
                quote namespace end)

    emit = MacroTools.postwalk(rmlines ∘ unblock, emit)
    emit
end

function parse_longdef_function(expr::Expr)
    commands = Any[]
    variable_declarations = Dict()
    namespace = Any[]
    @capture(expr, function fn_(args__) body__ end) || error("ParseError (parse_function): parsing took invalid branch (syntax match failure).")
    for ex in body
        new = MacroTools.postwalk(ex) do e

            if @capture(e, v_[a_] ~ d_)
                !(v in keys(variable_declarations)) && error("ParseError (parse_block): IdArray must be declared before use.")
                e = Expr(:call, GlobalRef(SPPL, :Sample), quote $v[$a] end, d)

            elseif @capture(e, v_ ~ d_)
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :id), QuoteNode(v)))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :id), QuoteNode(v))))
                end
                e = Expr(:call, GlobalRef(SPPL, :Sample), v, d)

            elseif @capture(e, v_ = array(n_))
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :IdArray), QuoteNode(v), n))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :IdArray), QuoteNode(v), n)))
                end
                e = Expr(:noop)

            elseif @capture(e, v_[a_] .> d_)
                !(v in keys(variable_declarations)) && error("ParseError (parse_block): IdArray must be declared before use.")
                e = Expr(:call, GlobalRef(SPPL, :Transform), quote $v[$a] end, d)

            elseif @capture(e, v_ .> d_)
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :Id), QuoteNode(v)))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :Id), QuoteNode(v))))
                end
                e = Expr(:call, GlobalRef(SPPL, :Transform), v, d)

            elseif @capture(e, v_ == d_)
                Expr(:call, :(<<), v, Expr(:call, GlobalRef(SPPL, :set), d))

            elseif @capture(e, if cond_ body1__ else body2__ end)
                Expr(:call, GlobalRef(SPPL, :IfElse), cond,
                     length(body1) == 1 ? body1[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body1...),
                     true,
                     length(body2) == 1 ? body2[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body2...))

            elseif @capture(e, for ind_ in stx_ : endx_ body_ end)
                Expr(:call, GlobalRef(SPPL, :For), stx, endx, Expr(:->, ind, body))

            elseif @capture(e, cond_ ? body1__ : body2__)
                Expr(:call, GlobalRef(SPPL, :IfElse), cond,
                     length(body1) == 1 ? body1[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body1...),
                     true,
                     length(body2) == 1 ? body2[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body2...))

            else
                e

            end
        end

        push!(commands, new)
    end

    # Filter commands to remove :noop expressions caused by array declarations exprs (see this part of the conditional matching above).
    commands = filter(commands) do expr
        expr isa Expr && expr.head != :noop
    end

    # Transformed body of method.
    new_body = Expr(:block, values(variable_declarations)...,
                    Expr(:(=), :command, Expr(:call, GlobalRef(SPPL, :Sequence), commands...)),
                    quote model = command.interpret() end,
                    Expr(:(=), :namespace, Expr(:tuple, namespace..., Expr(:(=), :model, :model))),
                    quote namespace end)

    emit = quote function $fn($(args...))
            $new_body
        end
    end
    MacroTools.postwalk(rmlines ∘ unblock, emit)
end

function parse_anonymous_function(expr::Expr)
    commands = Any[]
    variable_declarations = Dict()
    namespace = Any[]
    @capture(expr, (args__) -> body__) || error("ParseError (parse_anonymous_function): parsing took invalid branch (syntax match failure).")
    for ex in body
        new = MacroTools.postwalk(ex) do e

            if @capture(e, v_[a_] ~ d_)
                !(v in keys(variable_declarations)) && error("ParseError (parse_block): IdArray must be declared before use.")
                e = Expr(:call, GlobalRef(SPPL, :Sample), quote $v[$a] end, d)

            elseif @capture(e, v_ ~ d_)
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :Id), QuoteNode(v)))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :Id), QuoteNode(v))))
                end
                e = Expr(:call, GlobalRef(SPPL, :Sample), v, d)

            elseif @capture(e, v_ = array(n_))
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :IdArray), QuoteNode(v), n))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :IdArray), QuoteNode(v), n)))
                end
                e = Expr(:noop)

            elseif @capture(e, v_[a_] .> d_)
                !(v in keys(variable_declarations)) && error("ParseError (parse_block): IdArray must be declared before use.")
                e = Expr(:call, GlobalRef(SPPL, :Transform), quote $v[$a] end, d)

            elseif @capture(e, v_ .> d_)
                !(v in keys(variable_declarations)) && begin
                    variable_declarations[v] = Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :id), QuoteNode(v)))
                    push!(namespace, Expr(:(=), v, Expr(:call, GlobalRef(SPPL, :id), QuoteNode(v))))
                end
                e = Expr(:call, GlobalRef(SPPL, :Transform), v, d)

            elseif @capture(e, v_ == d_)
                Expr(:call, :(<<), v, Expr(:call, GlobalRef(SPPL, :set), d))

            elseif @capture(e, if cond_ body1__ else body2__ end)
                Expr(:call, GlobalRef(SPPL, :IfElse), cond,
                     length(body1) == 1 ? body1[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body1...),
                     true,
                     length(body2) == 1 ? body2[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body2...))

            elseif @capture(e, for ind_ in stx_ : endx_ body_ end)
                Expr(:call, GlobalRef(SPPL, :For), stx, endx, Expr(:->, ind, body))

            elseif @capture(e, cond_ ? body1__ : body2__)
                Expr(:call, GlobalRef(SPPL, :IfElse), cond,
                     length(body1) == 1 ? body1[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body1...),
                     true,
                     length(body2) == 1 ? body2[1] : Expr(:call, GlobalRef(SPPL, :Sequence), body2...))

            else
                e

            end
        end

        push!(commands, new)
    end

    # Transformed body of method.
    new_body = Expr(:block, values(variable_declarations)...,
                    Expr(:(=), :command, Expr(:call, GlobalRef(SPPL, :Sequence), commands...)),
                    quote model = command.interpret() end,
                    Expr(:(=), :namespace, Expr(:tuple, namespace..., Expr(:(=), :model, :model))),
                    quote namespace end)

    emit = Expr(:->, Expr(:tuple, args...), new_body)
    MacroTools.postwalk(rmlines ∘ unblock, emit)
end

function _sppl(expr::Expr)
    expr.head == :block && return parse_block(expr)
    expr.head == :function && return parse_longdef_function(expr)
    expr.head == :-> && return parse_anonymous_function(expr)
    if expr.head == :(=)
        longdef = MacroTools.longdef(expr)
        longdef.head == :function && return parse_longdef_function(longdef)
    end
    error("ParseError (@sppl): requires a block, a longdef function definition, a shortdef function definition, or an anonymous function definition.")
end

macro sppl(expr)
    new = _sppl(expr)
    esc(new)
end

macro sppl(debug, expr)
    new = _sppl(expr)
    debug == :debug && println(new)
    esc(new)
end

# String macro.
macro sppl_str(debug_flag, str)
    comp = compiler(str)
    debug_flag == :debug && println(comp.render_module())
    comp.execute_module()
end

macro sppl_str(str)
    compiler(str).execute_module()
end

export @sppl, @sppl_str

end # module


text:
"""
$(SIGNATURES)

Compute `log(sum(exp, X))` in a numerically stable way that avoids intermediate over- and
underflow.

`X` should be an iterator of real or complex numbers. The result is computed using a single
pass over the data.

# References

[Sebastian Nowozin: Streaming Log-sum-exp Computation](http://www.nowozin.net/sebastian/blog/streaming-log-sum-exp-computation.html)
"""
logsumexp(X) = _logsumexp_onepass(X)

"""
$(SIGNATURES)

Compute `log.(sum(exp.(X); dims=dims))` in a numerically stable way that avoids
intermediate over- and underflow.

The result is computed using a single pass over the data.

# References

[Sebastian Nowozin: Streaming Log-sum-exp Computation](http://www.nowozin.net/sebastian/blog/streaming-log-sum-exp-computation.html)
"""
logsumexp(X::AbstractArray{<:Number}; dims=:) = _logsumexp(X, dims)

_logsumexp(X::AbstractArray{<:Number}, ::Colon) = _logsumexp_onepass(X)
function _logsumexp(X::AbstractArray{<:Number}, dims)
    # Do not use log(zero(eltype(X))) directly to avoid issues with ForwardDiff (#82)
    FT = float(eltype(X))
    xmax_r = reduce(_logsumexp_onepass_op, X; dims=dims, init=(FT(-Inf), zero(FT)))
    return @. first(xmax_r) + log1p(last(xmax_r))
end

function _logsumexp_onepass(X)
    # fallback for empty collections
    isempty(X) && return log(sum(X))
    return _logsumexp_onepass_result(_logsumexp_onepass_reduce(X, Base.IteratorEltype(X)))
end

# function barrier for reductions with single element and without initial element
_logsumexp_onepass_result(x) = float(x)
_logsumexp_onepass_result((xmax, r)::Tuple) = xmax + log1p(r)

# iterables with known element type
function _logsumexp_onepass_reduce(X, ::Base.HasEltype)
    # do not perform type computations if element type is abstract
    T = eltype(X)
    isconcretetype(T) || return _logsumexp_onepass_reduce(X, Base.EltypeUnknown())

    FT = float(T)
    return reduce(_logsumexp_onepass_op, X; init=(FT(-Inf), zero(FT)))
end

# iterables without known element type
_logsumexp_onepass_reduce(X, ::Base.EltypeUnknown) = reduce(_logsumexp_onepass_op, X)

## Reductions for one-pass algorithm: avoid expensive multiplications if numbers are reduced

# reduce two numbers
function _logsumexp_onepass_op(x1::T, x2::T) where {T<:Number}
    xmax, a = if x1 == x2
        # handle `x1 = x2 = ±Inf` correctly
        x2, zero(x1 - x2)
    elseif isnan(x1) || isnan(x2)
        # ensure that `NaN` is propagated correctly for complex numbers
        z = oftype(x1, NaN)
        z, exp(z)
    elseif real(x1) > real(x2)
        x1, x2 - x1
    else
        x2, x1 - x2
    end
    r = exp(a)
    return xmax, r
end
_logsumexp_onepass_op(x1::Number, x2::Number) = _logsumexp_onepass_op(promote(x1, x2)...)

# reduce a number and a partial sum
_logsumexp_onepass_op(x::Number, (xmax, r)::Tuple{<:Number,<:Number}) =
    _logsumexp_onepass_op(x, xmax, r)
_logsumexp_onepass_op((xmax, r)::Tuple{<:Number,<:Number}, x::Number) =
    _logsumexp_onepass_op(x, xmax, r)
_logsumexp_onepass_op(x::Number, xmax::Number, r::Number) =
    _logsumexp_onepass_op(promote(x, xmax)..., r)
function _logsumexp_onepass_op(x::T, xmax::T, r::Number) where {T<:Number}
    _xmax, _r = if x == xmax
        # handle `x = xmax = ±Inf` correctly
        xmax, r + exp(zero(x - xmax))
    elseif isnan(x) || isnan(xmax)
        # ensure that `NaN` is propagated correctly for complex numbers
        z = oftype(x, NaN)
        z, r + exp(z)
    elseif real(x) > real(xmax)
        x, (r + one(r)) * exp(xmax - x)
    else
        xmax, r + exp(x - xmax)
    end
    return _xmax, _r
end

# reduce two partial sums
function _logsumexp_onepass_op(
    (xmax1, r1)::Tuple{<:Number,<:Number}, (xmax2, r2)::Tuple{<:Number,<:Number}
)
    return _logsumexp_onepass_op(xmax1, xmax2, r1, r2)
end
function _logsumexp_onepass_op(xmax1::Number, xmax2::Number, r1::Number, r2::Number)
    return _logsumexp_onepass_op(promote(xmax1, xmax2)..., promote(r1, r2)...)
end
function _logsumexp_onepass_op(xmax1::T, xmax2::T, r1::R, r2::R) where {T<:Number,R<:Number}
    xmax, r = if xmax1 == xmax2
        # handle `xmax1 = xmax2 = ±Inf` correctly
        xmax2, r2 + (r1 + one(r1)) * exp(zero(xmax1 - xmax2))
    elseif isnan(xmax1) || isnan(xmax2)
        # ensure that `NaN` is propagated correctly for complex numbers
        z = oftype(xmax1, NaN)
        z, r1 + exp(z)
    elseif real(xmax1) > real(xmax2)
        xmax1, r1 + (r2 + one(r2)) * exp(xmax2 - xmax1)
    else
        xmax2, r2 + (r1 + one(r1)) * exp(xmax1 - xmax2)
    end
    return xmax, r
end


text:
# #############################################################################
# #############################################################################
#Julia wrapper for C mode solver

#This file contains the Julia wrapper for running the internal mode solver written in C (using the GSL library). The following function is provided for the mode searcher:

#   modebounces = findmode_gsl(bnd::Boundary,idx::RefractiveIndex, init::Array{Float64,1},order::Int64;rtol::Float64=1e-5,maxiter::Int64=40)
#   Use Newton's method to search for a nearby value of (<theta>,<chi>) or (angular position,angle of incidence) close to the initial trial value <init> (entered as the array [<theta0>,<chi0>]), such that the trajectory of a ray beginning in that configuration is periodic with <order> bounces (that is on the <order>th following bounce the ray returns to within a distance measure tolerance <rtol> (default 1e-5) of (<theta>,<chi>)).
#   Returns the 2D array <modebounces> which has as its rows the (<theta>,<chi>) or (angular position,angle of incidence) values of each bounce in one cycle of a periodic mode.
#   The search is aborted and a NaN array is returned if there is a Jacobian computation error, oscillatory solution error, or <maxiter> iterations (default 40) has passed without finding a solution.
#   This function directly runs the GSL rootfinding algorithms on the ray solver C code, since the Julia wrapping only provides data recording and primitive analysis which is not required here.

# #############################################################################
# #############################################################################
#Initiate

#Dependencies
#require("basic.jl")
#require("boundary.jl")
#require("refractive_index.jl")
#require("ray_solver.jl")

# #############################################################################
# #############################################################################
#Wrapper for GSL mode finding

#Search for periodic modes (GSL multidimensional root solver)
#Use Newton's method to search for a nearby mode
function findmode_gsl(bnd::Boundary,idx::RefractiveIndex,init::Array{Float64,1},order::Int64;rtol::Float64=1e-5,maxiter::Int64=40)

    #Preallocate results array
    modebounces::Array{Float64,1} = Array(Float64,2*order)

    #Make C call
    status::Int32 = ccall((:findmode,"libcavchaos.so"), Cint,
        #Tuple of argument types
        (Clong,Ptr{Cdouble},
         Cdouble,Cdouble,
         Cdouble,Clong,
         Any,Ptr{Void},Ptr{Void},Any,Ptr{Void},Ptr{Void}),
        #Argument values
        order,modebounces, #mode-specific variables
        init[1],init[2], #initial conditions
        rtol,maxiter, #root-finding algorithm parameters
        bnd,rfunc_p,rsys!_p,idx,nfunc_p,nderiv!_p) #Cavity parameters

    #Return NaN on abortions or false positives (almost identical points at high chi)
    if (status == 1) || (var(modebounces[1:order]) < 1e-3)
        return nans(1,1)::Array{Float64,2}
    end

    #Return array where the rows are the (theta,chi) values of each bounce along the trajectory in one cycle of a periodic mode
    return reshape(modebounces,order,2)::Array{Float64,2}

end


text:
# © 2016 Massachusetts Institute of Technology.  See LICENSE file for details.
if filemode(Pkg.dir("Seep", "kernels.ptx")) == 0
  error("Seep GPU (kernels.ptx) can not be found. Try Pkg.build(\"Seep\")")
end

const md = CuModuleFile(Pkg.dir("Seep", "kernels.ptx"))
#__init__() = global md = CuModule(Pkg.dir("Seep") * "/kernels.ptx", false)

cutype(ex::Symbol) = ex
cutype(ex::Expr) = ex.head == :(&) ? :(CudaArray{$(ex.args[1])}) : ex

@compat (::Type{CudaArray{T}}){T}(i::Integer...) = CudaArray(T, i...)
Base.ones(a::CudaArray) = let s = similar(a); fill!(s, one(eltype(s))); s end
Base.zeros(a::CudaArray) = let s = similar(a); fill!(s, zero(eltype(s))); s end
@compat (::Type{CudaArray{T}}){T}(::Type{CudaArray{T}}, i::Int...) = CudaArray(T, i...)
Base.eltype{T}(::Type{CudaArray{T}}) = T

Base.reshape(x::CudaArray, i...) = reinterpret(eltype(x), x, i)

include("cudahacks_common.jl")

const STREAM=CuStream[CUDAdrv.default_stream()]

function cuda_kernel(name, signature, templates, text)
    block = quote
        global $(Symbol(name))
    end

    hashname = "$(name)_$(hexstring(sha1(text)))"

    if isempty(templates)
        push!(block.args, "no templates")
    else
        for type_map in TemplateIterator(templates)
            typed_sig = replace_type_parameters(signature, type_map)
            kernel_name = "$(hashname)_$(type_names(templates, type_map))"

            push!(block.args, :(try
                    global const $(Symbol(kernel_name)) = CuFunction(md, $kernel_name)
                catch e
                    println($("Unable to load cuda function for $kernel_name.  Try Pkg.build(\"Seep\")."))
                    rethrow(e)
                end
            ))

            ca = :($(Symbol(name))())
            for i in typed_sig
                push!(ca.args, :($(i[2])::$(cutype(i[1]))))
            end

            def = :(CUDAdrv.launch($(Symbol(kernel_name)), CUDAdrv.CuDim3(Int(div(n+127,128))), CUDAdrv.CuDim3(128), (), stream=STREAM[1]))
            for a in typed_sig
                if eval(cutype(a[1])) <: CudaArray
                   push!(def.args[end-1].args, :(Base.unsafe_convert(Ptr, $(a[2]).ptr)))
                else
                   push!(def.args[end-1].args, a[2])
                end
            end

            push!(block.args, :($ca = $def))
        end
    end

    return block
end


text:
struct FilteredSRBelief{B, A, NF, NB}
    b0::B
    a::A
    nf::NF
    srb::NB
end

function Base.rand(rng::AbstractRNG, b::FilteredSRBelief)
    s = rand(rng, b.b0)
    sp, r = generate_sr(b.srb.model, s, b.a, rng)
    POMCPOW.push_weighted!(b.srb, b.nf, s, sp, r)
    return rand(rng, b.srb)
end