text:
# TODO: remove `vars` hack that avoids https://github.com/Alexander-Barth/NCDatasets.jl/issues/135

mutable struct NetCDFIO_Stats
    root_grp::NC.NCDataset{Nothing}
    profiles_grp::NC.NCDataset{NC.NCDataset{Nothing}}
    ts_grp::NC.NCDataset{NC.NCDataset{Nothing}}
    grid::Grid
    last_output_time::Float64
    uuid::String
    frequency::Float64
    stats_path::String
    path_plus_file::String
    vars::Dict{String, Any} # Hack to avoid https://github.com/Alexander-Barth/NCDatasets.jl/issues/135
    function NetCDFIO_Stats(namelist, grid::Grid)

        # Initialize properties with valid type:
        tmp = tempname()
        root_grp = NC.Dataset(tmp, "c")
        NC.defGroup(root_grp, "profiles")
        NC.defGroup(root_grp, "timeseries")
        profiles_grp = root_grp.group["profiles"]
        ts_grp = root_grp.group["timeseries"]
        close(root_grp)

        last_output_time = 0.0
        uuid = string(namelist["meta"]["uuid"])

        frequency = namelist["stats_io"]["frequency"]

        # Setup the statistics output path
        simname = namelist["meta"]["simname"]
        casename = namelist["meta"]["casename"]
        outpath = joinpath(namelist["output"]["output_root"], "Output.$simname.$uuid")
        mkpath(outpath)

        stats_path = joinpath(outpath, namelist["stats_io"]["stats_dir"])
        mkpath(stats_path)

        path_plus_file = joinpath(stats_path, "Stats.$simname.nc")

        # TODO: uncomment restart
        # if isfile(path_plus_file)
        #   @inbounds for i in 1:100
        #         res_name = "Restart_$i"
        #         if isfile(path_plus_file)
        #             path_plus_file = stats_path * "Stats.$simname.$res_name.nc"
        #         else
        #             break
        #         end
        #     end
        # end

        # Write namelist file to output directory
        open(joinpath(outpath, "namelist_$casename.in"), "w") do io
            JSON.print(io, namelist, 4)
        end

        # Remove the NC file if it exists, in case it accidentally wasn't closed
        isfile(path_plus_file) && rm(path_plus_file; force = true)

        NC.Dataset(path_plus_file, "c") do root_grp

            zf = vec(grid.zf)
            zc = vec(grid.zc)

            # Set profile dimensions
            profile_grp = NC.defGroup(root_grp, "profiles")
            NC.defDim(profile_grp, "zf", grid.nz + 1)
            NC.defDim(profile_grp, "zc", grid.nz)
            NC.defDim(profile_grp, "t", Inf)
            NC.defVar(profile_grp, "zf", zf, ("zf",))
            NC.defVar(profile_grp, "zc", zc, ("zc",))
            NC.defVar(profile_grp, "t", Float64, ("t",))

            reference_grp = NC.defGroup(root_grp, "reference")
            NC.defDim(reference_grp, "zf", grid.nz + 1)
            NC.defDim(reference_grp, "zc", grid.nz)
            NC.defVar(reference_grp, "zf", zf, ("zf",))
            NC.defVar(reference_grp, "zc", zc, ("zc",))

            ts_grp = NC.defGroup(root_grp, "timeseries")
            NC.defDim(ts_grp, "t", Inf)
            NC.defVar(ts_grp, "t", Float64, ("t",))
        end
        vars = Dict{String, Any}()
        return new(
            root_grp,
            profiles_grp,
            ts_grp,
            grid,
            last_output_time,
            uuid,
            frequency,
            stats_path,
            path_plus_file,
            vars,
        )
    end
end

function open_files(self)
    self.root_grp = NC.Dataset(self.path_plus_file, "a")
    self.profiles_grp = self.root_grp.group["profiles"]
    self.ts_grp = self.root_grp.group["timeseries"]
    vars = self.vars

    # Hack to avoid https://github.com/Alexander-Barth/NCDatasets.jl/issues/135
    vars["profiles"] = Dict{String, Any}()
    for k in keys(self.profiles_grp)
        vars["profiles"][k] = self.profiles_grp[k]
    end
    vars["timeseries"] = Dict{String, Any}()
    for k in keys(self.ts_grp)
        vars["timeseries"][k] = self.ts_grp[k]
    end
end

function close_files(self::NetCDFIO_Stats)
    close(self.root_grp)
end

#####
##### Generic field
#####

function add_field(self::NetCDFIO_Stats, var_name::String; dims, group)
    NC.Dataset(self.path_plus_file, "a") do root_grp
        profile_grp = root_grp.group[group]
        new_var = NC.defVar(profile_grp, var_name, Float64, dims)
    end
end

#####
##### Time-series data
#####

function add_ts(self::NetCDFIO_Stats, var_name::String)
    NC.Dataset(self.path_plus_file, "a") do root_grp
        ts_grp = root_grp.group["timeseries"]
        new_var = NC.defVar(ts_grp, var_name, Float64, ("t",))
    end
end

#####
##### Performance critical IO
#####

# Field wrapper
write_field(self::NetCDFIO_Stats, var_name::String, data; group) = write_field(self, var_name, vec(data); group = group)

function write_field(self::NetCDFIO_Stats, var_name::String, data::T; group) where {T <: AbstractArray{Float64, 1}}
    if group == "profiles"
        # Hack to avoid https://github.com/Alexander-Barth/NCDatasets.jl/issues/135
        @inbounds self.vars[group][var_name][:, end] = data
        # Ideally, we remove self.vars and use:
        # var = self.profiles_grp[var_name]
        # Not sure why `end` instead of `end+1`, but `end+1` produces garbage output
        # @inbounds var[end, :] = data :: T
    elseif group == "reference"
        NC.Dataset(self.path_plus_file, "a") do root_grp
            reference_grp = root_grp.group[group]
            var = reference_grp[var_name]
            var .= data::T
        end
    else
        error("Bad group given")
    end
end

function write_ts(self::NetCDFIO_Stats, var_name::String, data::Float64)
    # Hack to avoid https://github.com/Alexander-Barth/NCDatasets.jl/issues/135
    @inbounds self.vars["timeseries"][var_name][end] = data::Float64
    # Ideally, we remove self.vars and use:
    # var = self.ts_grp[var_name]
    # @inbounds var[end+1] = data :: Float64
end

function write_simulation_time(self::NetCDFIO_Stats, t::Float64)
    # # Write to profiles group
    profile_t = self.profiles_grp["t"]
    @inbounds profile_t[end + 1] = t::Float64

    # # Write to timeseries group
    ts_t = self.ts_grp["t"]
    @inbounds ts_t[end + 1] = t::Float64
end

ext: jl


text:
# Automatically generated using Clang.jl

const IVIDMM_MAJOR_VERSION = Int32(4)
const IVIDMM_MINOR_VERSION = Int32(0)
const IVIDMM_CLASS_SPEC_MAJOR_VERSION = Int32(3)
const IVIDMM_CLASS_SPEC_MINOR_VERSION = Int32(0)
const IVIDMM_DRIVER_VENDOR = "National Instruments"
const IVIDMM_DRIVER_DESCRIPTION = "IviDmm Class Driver"
const IVIDMM_VAL_MAX_TIME_INFINITE = IVI_VAL_MAX_TIME_INFINITE
const IVIDMM_VAL_MAX_TIME_IMMEDIATE = IVI_VAL_MAX_TIME_IMMEDIATE
const IVIDMM_ATTR_CACHE = IVI_ATTR_CACHE
const IVIDMM_ATTR_RANGE_CHECK = IVI_ATTR_RANGE_CHECK
const IVIDMM_ATTR_QUERY_INSTRUMENT_STATUS = IVI_ATTR_QUERY_INSTRUMENT_STATUS
const IVIDMM_ATTR_RECORD_COERCIONS = IVI_ATTR_RECORD_COERCIONS
const IVIDMM_ATTR_SIMULATE = IVI_ATTR_SIMULATE
const IVIDMM_ATTR_INTERCHANGE_CHECK = IVI_ATTR_INTERCHANGE_CHECK
const IVIDMM_ATTR_SPY = IVI_ATTR_SPY
const IVIDMM_ATTR_USE_SPECIFIC_SIMULATION = IVI_ATTR_USE_SPECIFIC_SIMULATION
const IVIDMM_ATTR_GROUP_CAPABILITIES = IVI_ATTR_GROUP_CAPABILITIES
const IVIDMM_ATTR_FUNCTION_CAPABILITIES = IVI_ATTR_FUNCTION_CAPABILITIES
const IVIDMM_ATTR_CLASS_DRIVER_PREFIX = IVI_ATTR_CLASS_DRIVER_PREFIX
const IVIDMM_ATTR_CLASS_DRIVER_VENDOR = IVI_ATTR_CLASS_DRIVER_VENDOR
const IVIDMM_ATTR_CLASS_DRIVER_DESCRIPTION = IVI_ATTR_CLASS_DRIVER_DESCRIPTION
const IVIDMM_ATTR_CLASS_DRIVER_CLASS_SPEC_MAJOR_VERSION = IVI_ATTR_CLASS_DRIVER_CLASS_SPEC_MAJOR_VERSION
const IVIDMM_ATTR_CLASS_DRIVER_CLASS_SPEC_MINOR_VERSION = IVI_ATTR_CLASS_DRIVER_CLASS_SPEC_MINOR_VERSION
const IVIDMM_ATTR_SPECIFIC_DRIVER_PREFIX = IVI_ATTR_SPECIFIC_DRIVER_PREFIX
const IVIDMM_ATTR_SPECIFIC_DRIVER_LOCATOR = IVI_ATTR_SPECIFIC_DRIVER_LOCATOR
const IVIDMM_ATTR_IO_RESOURCE_DESCRIPTOR = IVI_ATTR_IO_RESOURCE_DESCRIPTOR
const IVIDMM_ATTR_LOGICAL_NAME = IVI_ATTR_LOGICAL_NAME
const IVIDMM_ATTR_SPECIFIC_DRIVER_VENDOR = IVI_ATTR_SPECIFIC_DRIVER_VENDOR
const IVIDMM_ATTR_SPECIFIC_DRIVER_DESCRIPTION = IVI_ATTR_SPECIFIC_DRIVER_DESCRIPTION
const IVIDMM_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MAJOR_VERSION = IVI_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MAJOR_VERSION
const IVIDMM_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MINOR_VERSION = IVI_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MINOR_VERSION
const IVIDMM_ATTR_INSTRUMENT_FIRMWARE_REVISION = IVI_ATTR_INSTRUMENT_FIRMWARE_REVISION
const IVIDMM_ATTR_INSTRUMENT_MANUFACTURER = IVI_ATTR_INSTRUMENT_MANUFACTURER
const IVIDMM_ATTR_INSTRUMENT_MODEL = IVI_ATTR_INSTRUMENT_MODEL
const IVIDMM_ATTR_SUPPORTED_INSTRUMENT_MODELS = IVI_ATTR_SUPPORTED_INSTRUMENT_MODELS
const IVIDMM_ATTR_CLASS_DRIVER_REVISION = IVI_ATTR_CLASS_DRIVER_REVISION
const IVIDMM_ATTR_SPECIFIC_DRIVER_REVISION = IVI_ATTR_SPECIFIC_DRIVER_REVISION
const IVIDMM_ATTR_DRIVER_SETUP = IVI_ATTR_DRIVER_SETUP
const IVIDMM_ATTR_FUNCTION = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(1)
const IVIDMM_ATTR_RANGE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(2)
const IVIDMM_ATTR_RESOLUTION_ABSOLUTE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(8)
const IVIDMM_ATTR_TRIGGER_SOURCE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(4)
const IVIDMM_ATTR_TRIGGER_DELAY = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(5)
const IVIDMM_ATTR_AC_MIN_FREQ = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(6)
const IVIDMM_ATTR_AC_MAX_FREQ = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(7)
const IVIDMM_ATTR_FREQ_VOLTAGE_RANGE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(101)
const IVIDMM_ATTR_TEMP_TRANSDUCER_TYPE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(201)
const IVIDMM_ATTR_TEMP_TC_TYPE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(231)
const IVIDMM_ATTR_TEMP_TC_REF_JUNC_TYPE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(232)
const IVIDMM_ATTR_TEMP_TC_FIXED_REF_JUNC = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(233)
const IVIDMM_ATTR_TEMP_RTD_ALPHA = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(241)
const IVIDMM_ATTR_TEMP_RTD_RES = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(242)
const IVIDMM_ATTR_TEMP_THERMISTOR_RES = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(251)
const IVIDMM_ATTR_SAMPLE_COUNT = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(301)
const IVIDMM_ATTR_SAMPLE_TRIGGER = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(302)
const IVIDMM_ATTR_SAMPLE_INTERVAL = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(303)
const IVIDMM_ATTR_TRIGGER_COUNT = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(304)
const IVIDMM_ATTR_MEAS_COMPLETE_DEST = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(305)
const IVIDMM_ATTR_TRIGGER_SLOPE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(334)
const IVIDMM_ATTR_APERTURE_TIME = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(321)
const IVIDMM_ATTR_APERTURE_TIME_UNITS = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(322)
const IVIDMM_ATTR_AUTO_RANGE_VALUE = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(331)
const IVIDMM_ATTR_AUTO_ZERO = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(332)
const IVIDMM_ATTR_POWERLINE_FREQ = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(333)
const IVIDMM_VAL_DC_VOLTS = Int32(1)
const IVIDMM_VAL_AC_VOLTS = Int32(2)
const IVIDMM_VAL_DC_CURRENT = Int32(3)
const IVIDMM_VAL_AC_CURRENT = Int32(4)
const IVIDMM_VAL_2_WIRE_RES = Int32(5)
const IVIDMM_VAL_4_WIRE_RES = Int32(101)
const IVIDMM_VAL_AC_PLUS_DC_VOLTS = Int32(106)
const IVIDMM_VAL_AC_PLUS_DC_CURRENT = Int32(107)
const IVIDMM_VAL_FREQ = Int32(104)
const IVIDMM_VAL_PERIOD = Int32(105)
const IVIDMM_VAL_TEMPERATURE = Int32(108)
const IVIDMM_VAL_FUNC_CLASS_EXT_BASE = Int32(500)
const IVIDMM_VAL_FUNC_SPECIFIC_EXT_BASE = Int32(1000)
const IVIDMM_VAL_AUTO_RANGE_ON = -1.0
const IVIDMM_VAL_AUTO_RANGE_OFF = -2.0
const IVIDMM_VAL_AUTO_RANGE_ONCE = -3.0
const IVIDMM_VAL_RANGE_CLASS_EXT_BASE = -100.0
const IVIDMM_VAL_RANGE_SPECIFIC_EXT_BASE = -1000.0
const IVIDMM_VAL_FREQ_VOLT_RANGE_CLASS_EXT_BASE = -(Float64(100.0))
const IVIDMM_VAL_FREQ_VOLT_RANGE_SPECIFIC_EXT_BASE = -(Float64(1000.0))
const IVIDMM_VAL_AUTO_DELAY_ON = -(Float64(1.0))
const IVIDMM_VAL_AUTO_DELAY_OFF = -(Float64(2.0))
const IVIDMM_VAL_TRIGGER_DELAY_CLASS_EXT_BASE = -(Float64(100.0))
const IVIDMM_VAL_TRIGGER_DELAY_SPECIFIC_EXT_BASE = -(Float64(1000.0))
const IVIDMM_VAL_IMMEDIATE = Int32(1)
const IVIDMM_VAL_EXTERNAL = Int32(2)
const IVIDMM_VAL_SOFTWARE_TRIG = Int32(3)
const IVIDMM_VAL_TTL0 = Int32(111)
const IVIDMM_VAL_TTL1 = Int32(112)
const IVIDMM_VAL_TTL2 = Int32(113)
const IVIDMM_VAL_TTL3 = Int32(114)
const IVIDMM_VAL_TTL4 = Int32(115)
const IVIDMM_VAL_TTL5 = Int32(116)
const IVIDMM_VAL_TTL6 = Int32(117)
const IVIDMM_VAL_TTL7 = Int32(118)
const IVIDMM_VAL_ECL0 = Int32(119)
const IVIDMM_VAL_ECL1 = Int32(120)
const IVIDMM_VAL_PXI_STAR = Int32(131)
const IVIDMM_VAL_RTSI_0 = Int32(140)
const IVIDMM_VAL_RTSI_1 = Int32(141)
const IVIDMM_VAL_RTSI_2 = Int32(142)
const IVIDMM_VAL_RTSI_3 = Int32(143)
const IVIDMM_VAL_RTSI_4 = Int32(144)
const IVIDMM_VAL_RTSI_5 = Int32(145)
const IVIDMM_VAL_RTSI_6 = Int32(146)
const IVIDMM_VAL_TRIGGER_SOURCE_CLASS_EXT_BASE = Int32(500)
const IVIDMM_VAL_TRIGGER_SOURCE_SPECIFIC_EXT_BASE = Int32(1000)
const IVIDMM_VAL_THERMOCOUPLE = Int32(1)
const IVIDMM_VAL_THERMISTOR = Int32(2)
const IVIDMM_VAL_2_WIRE_RTD = Int32(3)
const IVIDMM_VAL_4_WIRE_RTD = Int32(4)
const IVIDMM_VAL_TRANSDUCER_CLASS_EXT_BASE = Int32(100)
const IVIDMM_VAL_TRANSDUCER_SPECIFIC_EXT_BASE = Int32(1000)
const IVIDMM_VAL_TEMP_REF_JUNC_INTERNAL = Int32(1)
const IVIDMM_VAL_TEMP_REF_JUNC_FIXED = Int32(2)
const IVIDMM_VAL_TEMP_REF_JUNC_CLASS_EXT_BASE = Int32(100)
const IVIDMM_VAL_TEMP_REF_JUNC_SPECIFIC_EXT_BASE = Int32(1000)
const IVIDMM_VAL_TEMP_TC_B = Int32(1)
const IVIDMM_VAL_TEMP_TC_C = Int32(2)
const IVIDMM_VAL_TEMP_TC_D = Int32(3)
const IVIDMM_VAL_TEMP_TC_E = Int32(4)
const IVIDMM_VAL_TEMP_TC_G = Int32(5)
const IVIDMM_VAL_TEMP_TC_J = Int32(6)
const IVIDMM_VAL_TEMP_TC_K = Int32(7)
const IVIDMM_VAL_TEMP_TC_N = Int32(8)
const IVIDMM_VAL_TEMP_TC_R = Int32(9)
const IVIDMM_VAL_TEMP_TC_S = Int32(10)
const IVIDMM_VAL_TEMP_TC_T = Int32(11)
const IVIDMM_VAL_TEMP_TC_U = Int32(12)
const IVIDMM_VAL_TEMP_TC_V = Int32(13)
const IVIDMM_VAL_TEMP_TC_TYPE_CLASS_EXT_BASE = Int32(100)
const IVIDMM_VAL_TEMP_TC_TYPE_SPECIFIC_EXT_BASE = Int32(1000)
const IVIDMM_VAL_NONE = -(Int32(1))
const IVIDMM_VAL_INTERVAL = Int32(10)
const IVIDMM_VAL_POSITIVE = Int32(0)
const IVIDMM_VAL_NEGATIVE = Int32(1)
const IVIDMM_VAL_TRIGGER_SLOPE_CLASS_EXT_BASE = Int32(100)
const IVIDMM_VAL_TRIGGER_SLOPE_SPECIFIC_EXT_BASE = Int32(1000)
const IVIDMM_VAL_SECONDS = Int32(0)
const IVIDMM_VAL_POWER_LINE_CYCLES = Int32(1)
const IVIDMM_VAL_AUTO_ZERO_OFF = Int32(0)
const IVIDMM_VAL_AUTO_ZERO_ON = Int32(1)
const IVIDMM_VAL_AUTO_ZERO_ONCE = Int32(2)
const IVIDMM_VAL_AUTO_ZERO_CLASS_EXT_BASE = Int32(100)
const IVIDMM_VAL_AUTO_ZERO_SPECIFIC_EXT_BASE = Int32(1000)
const IVIDMM_WARN_OVER_RANGE = IVI_CLASS_WARN_BASE + 1
const IVIDMM_ERROR_TRIGGER_NOT_SOFTWARE = IVI_CROSS_CLASS_ERROR_BASE + 1
const IVIDMM_ERROR_MAX_TIME_EXCEEDED = IVI_CLASS_ERROR_BASE + 3
const IVIDMM_WRNMSG_OVER_RANGE = "Over range."
const IVIDMM_ERRMSG_MAX_TIME_EXCEEDED = "Max Time exceeded before "
const IVIDMM_ERRMSG_TRIGGER_NOT_SOFTWARE = "The trigger source is not set to "

# Skipping MacroDefinition: IVIDMM_ERROR_CODES_AND_MSGS { IVIDMM_WARN_OVER_RANGE , IVIDMM_WRNMSG_OVER_RANGE } , { IVIDMM_ERROR_MAX_TIME_EXCEEDED , IVIDMM_ERRMSG_MAX_TIME_EXCEEDED } , { IVIDMM_ERROR_TRIGGER_NOT_SOFTWARE , IVIDMM_ERRMSG_TRIGGER_NOT_SOFTWARE }

const NIDMM_MAJOR_VERSION = 17
const NIDMM_MINOR_VERSION = 1
const NIDMM_CLASS_SPEC_MAJOR_VERSION = 4
const NIDMM_CLASS_SPEC_MINOR_VERSION = 1
const NIDMM_ATTR_BASE = IVI_SPECIFIC_PUBLIC_ATTR_BASE
const NIDMM_ATTR_PRIVATE_BASE = IVI_SPECIFIC_PRIVATE_ATTR_BASE
const NIDMM_ERROR_BASE = IVI_SPECIFIC_ERROR_BASE
const NIDMM_WARN_BASE = IVI_SPECIFIC_WARN_BASE
const NIDMM_ERROR_EXT_STATUS_BASE = NIDMM_ERROR_BASE + 0x0f00
const NIDMM_ERROR_EXTCAL_ERROR_BASE = NIDMM_ERROR_BASE + 0x0200
const NIDMM_WARN_EXT_STATUS_BASE = NIDMM_WARN_BASE + 0x0f00
const NIDMM_WARN_EXTCAL_WARN_BASE = NIDMM_WARN_BASE + 0x0200
const NIDMM_VAL_FUNC_SPECIFIC_EXT_BASE = IVIDMM_VAL_FUNC_SPECIFIC_EXT_BASE
const NIDMM_VAL_TRIGGER_SOURCE_SPECIFIC_EXT_BASE = IVIDMM_VAL_TRIGGER_SOURCE_SPECIFIC_EXT_BASE
const NIDMM_WARN_NOT_SUPPORTED = NIDMM_WARN_BASE + Int32(0)
const NIDMM_WARN_SIMULATING = NIDMM_WARN_BASE + Int32(1)
const NIDMM_WARN_RANGE_INVALIDATED = NIDMM_WARN_BASE + Int32(2)
const NIDMM_WARN_UNDERRANGE = NIDMM_WARN_EXT_STATUS_BASE + 0x80
const NIDMM_WARN_OVERRANGE = IVIDMM_WARN_OVER_RANGE
const NIDMM_WARN_EXTCAL_SELF_CAL_NEEDED = NIDMM_WARN_EXTCAL_WARN_BASE + Int32(0)
const NIDMM_WARN_EXTCAL_BUFFER_TRUNCATED = NIDMM_WARN_EXTCAL_WARN_BASE + Int32(1)
const NIDMM_ATTR_RANGE_CHECK = IVI_ATTR_RANGE_CHECK
const NIDMM_ATTR_QUERY_INSTRUMENT_STATUS = IVI_ATTR_QUERY_INSTRUMENT_STATUS
const NIDMM_ATTR_CACHE = IVI_ATTR_CACHE
const NIDMM_ATTR_SIMULATE = IVI_ATTR_SIMULATE
const NIDMM_ATTR_RECORD_COERCIONS = IVI_ATTR_RECORD_COERCIONS
const NIDMM_ATTR_INTERCHANGE_CHECK = IVI_ATTR_INTERCHANGE_CHECK
const NIDMM_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MAJOR_VERSION = IVI_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MAJOR_VERSION
const NIDMM_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MINOR_VERSION = IVI_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MINOR_VERSION
const NIDMM_ATTR_SPECIFIC_DRIVER_DESCRIPTION = IVI_ATTR_SPECIFIC_DRIVER_DESCRIPTION
const NIDMM_ATTR_SPECIFIC_DRIVER_PREFIX = IVI_ATTR_SPECIFIC_DRIVER_PREFIX
const NIDMM_ATTR_SPECIFIC_DRIVER_VENDOR = IVI_ATTR_SPECIFIC_DRIVER_VENDOR
const NIDMM_ATTR_SPECIFIC_DRIVER_REVISION = IVI_ATTR_SPECIFIC_DRIVER_REVISION
const NIDMM_ATTR_CLASS_DRIVER_CLASS_SPEC_MAJOR_VERSION = IVI_ATTR_CLASS_DRIVER_CLASS_SPEC_MAJOR_VERSION
const NIDMM_ATTR_CLASS_DRIVER_CLASS_SPEC_MINOR_VERSION = IVI_ATTR_CLASS_DRIVER_CLASS_SPEC_MINOR_VERSION
const NIDMM_ATTR_CHANNEL_COUNT = IVI_ATTR_CHANNEL_COUNT
const NIDMM_ATTR_SUPPORTED_INSTRUMENT_MODELS = IVI_ATTR_SUPPORTED_INSTRUMENT_MODELS
const NIDMM_ATTR_GROUP_CAPABILITIES = IVI_ATTR_GROUP_CAPABILITIES
const NIDMM_ATTR_INSTRUMENT_MANUFACTURER = IVI_ATTR_INSTRUMENT_MANUFACTURER
const NIDMM_ATTR_INSTRUMENT_MODEL = IVI_ATTR_INSTRUMENT_MODEL
const NIDMM_ATTR_INSTRUMENT_FIRMWARE_REVISION = IVI_ATTR_INSTRUMENT_FIRMWARE_REVISION
const NIDMM_ATTR_LOGICAL_NAME = IVI_ATTR_LOGICAL_NAME
const NIDMM_ATTR_IO_RESOURCE_DESCRIPTOR = IVI_ATTR_IO_RESOURCE_DESCRIPTOR
const NIDMM_ATTR_DRIVER_SETUP = IVI_ATTR_DRIVER_SETUP
const NIDMM_ATTR_IO_SESSION = IVI_ATTR_IO_SESSION
const NIDMM_ATTR_FUNCTION = IVIDMM_ATTR_FUNCTION
const NIDMM_ATTR_RANGE = IVIDMM_ATTR_RANGE
const NIDMM_ATTR_RESOLUTION_ABSOLUTE = IVIDMM_ATTR_RESOLUTION_ABSOLUTE
const NIDMM_ATTR_RESOLUTION_DIGITS = IVI_CLASS_PUBLIC_ATTR_BASE + Int32(3)
const NIDMM_ATTR_TRIGGER_DELAY = IVIDMM_ATTR_TRIGGER_DELAY
const NIDMM_ATTR_TRIGGER_SOURCE = IVIDMM_ATTR_TRIGGER_SOURCE
const NIDMM_ATTR_AC_MAX_FREQ = IVIDMM_ATTR_AC_MAX_FREQ
const NIDMM_ATTR_AC_MIN_FREQ = IVIDMM_ATTR_AC_MIN_FREQ
const NIDMM_ATTR_FREQ_VOLTAGE_RANGE = IVIDMM_ATTR_FREQ_VOLTAGE_RANGE
const NIDMM_ATTR_MEAS_COMPLETE_DEST = IVIDMM_ATTR_MEAS_COMPLETE_DEST
const NIDMM_ATTR_SAMPLE_COUNT = IVIDMM_ATTR_SAMPLE_COUNT
const NIDMM_ATTR_SAMPLE_INTERVAL = IVIDMM_ATTR_SAMPLE_INTERVAL
const NIDMM_ATTR_SAMPLE_TRIGGER = IVIDMM_ATTR_SAMPLE_TRIGGER
const NIDMM_ATTR_TRIGGER_COUNT = IVIDMM_ATTR_TRIGGER_COUNT
const NIDMM_ATTR_APERTURE_TIME = IVIDMM_ATTR_APERTURE_TIME
const NIDMM_ATTR_APERTURE_TIME_UNITS = IVIDMM_ATTR_APERTURE_TIME_UNITS
const NIDMM_ATTR_AUTO_RANGE_VALUE = IVIDMM_ATTR_AUTO_RANGE_VALUE
const NIDMM_ATTR_AUTO_ZERO = IVIDMM_ATTR_AUTO_ZERO
const NIDMM_ATTR_POWERLINE_FREQ = IVIDMM_ATTR_POWERLINE_FREQ
const NIDMM_ATTR_TRIGGER_SLOPE = IVIDMM_ATTR_TRIGGER_SLOPE
const NIDMM_ATTR_SAMPLE_TRIGGER_SLOPE = NIDMM_ATTR_BASE + Int32(10)
const NIDMM_ATTR_MEAS_DEST_SLOPE = NIDMM_ATTR_BASE + Int32(2)
const NIDMM_ATTR_ADC_CALIBRATION = NIDMM_ATTR_BASE + Int32(22)
const NIDMM_ATTR_OFFSET_COMP_OHMS = NIDMM_ATTR_BASE + Int32(23)
const NIDMM_ATTR_NUMBER_OF_AVERAGES = NIDMM_ATTR_BASE + Int32(32)
const NIDMM_ATTR_CURRENT_SOURCE = NIDMM_ATTR_BASE + Int32(25)
const NIDMM_ATTR_DC_NOISE_REJECTION = NIDMM_ATTR_BASE + Int32(26)
const NIDMM_ATTR_SETTLE_TIME = NIDMM_ATTR_BASE + Int32(28)
const NIDMM_ATTR_INPUT_RESISTANCE = NIDMM_ATTR_BASE + Int32(29)
const NIDMM_ATTR_LATENCY = NIDMM_ATTR_BASE + Int32(34)
const NIDMM_ATTR_BUFFER_SIZE = NIDMM_ATTR_BASE + Int32(37)
const NIDMM_ATTR_SHUNT_VALUE = NIDMM_ATTR_BASE + Int32(3)
const NIDMM_ATTR_OPERATION_MODE = NIDMM_ATTR_BASE + Int32(14)
const NIDMM_ATTR_WAVEFORM_RATE = NIDMM_ATTR_BASE + Int32(18)
const NIDMM_ATTR_WAVEFORM_POINTS = NIDMM_ATTR_BASE + Int32(19)
const NIDMM_ATTR_WAVEFORM_COUPLING = NIDMM_ATTR_BASE + Int32(27)
const NIDMM_ATTR_FREQ_VOLTAGE_AUTO_RANGE_VALUE = NIDMM_ATTR_BASE + Int32(44)
const NIDMM_ATTR_CABLE_COMP_TYPE = NIDMM_ATTR_BASE + Int32(45)
const NIDMM_ATTR_SHORT_CABLE_COMP_REACTANCE = NIDMM_ATTR_BASE + Int32(46)
const NIDMM_ATTR_SHORT_CABLE_COMP_RESISTANCE = NIDMM_ATTR_BASE + Int32(47)
const NIDMM_ATTR_OPEN_CABLE_COMP_SUSCEPTANCE = NIDMM_ATTR_BASE + Int32(48)
const NIDMM_ATTR_OPEN_CABLE_COMP_CONDUCTANCE = NIDMM_ATTR_BASE + Int32(49)
const NIDMM_ATTR_LC_CALCULATION_MODEL = NIDMM_ATTR_BASE + Int32(52)
const NIDMM_ATTR_DC_BIAS = NIDMM_ATTR_BASE + Int32(53)
const NIDMM_ATTR_LC_NUMBER_MEAS_TO_AVERAGE = NIDMM_ATTR_BASE + Int32(55)
const NIDMM_ATTR_SERIAL_NUMBER = NIDMM_ATTR_BASE + Int32(54)
const NIDMM_ATTR_CONFIG_PRODUCT_NUMBER = NIDMM_ATTR_BASE + Int32(61)
const NIDMM_ATTR_TEMP_TRANSDUCER_TYPE = IVIDMM_ATTR_TEMP_TRANSDUCER_TYPE
const NIDMM_ATTR_TEMP_TC_REF_JUNC_TYPE = IVIDMM_ATTR_TEMP_TC_REF_JUNC_TYPE
const NIDMM_ATTR_TEMP_TC_TYPE = IVIDMM_ATTR_TEMP_TC_TYPE
const NIDMM_ATTR_TEMP_TC_FIXED_REF_JUNC = IVIDMM_ATTR_TEMP_TC_FIXED_REF_JUNC
const NIDMM_ATTR_TEMP_RTD_TYPE = NIDMM_ATTR_BASE + Int32(120)
const NIDMM_ATTR_TEMP_RTD_RES = IVIDMM_ATTR_TEMP_RTD_RES
const NIDMM_ATTR_TEMP_RTD_A = NIDMM_ATTR_BASE + Int32(121)
const NIDMM_ATTR_TEMP_RTD_B = NIDMM_ATTR_BASE + Int32(122)
const NIDMM_ATTR_TEMP_RTD_C = NIDMM_ATTR_BASE + Int32(123)
const NIDMM_ATTR_TEMP_THERMISTOR_TYPE = NIDMM_ATTR_BASE + Int32(124)
const NIDMM_ATTR_TEMP_THERMISTOR_A = NIDMM_ATTR_BASE + Int32(125)
const NIDMM_ATTR_TEMP_THERMISTOR_B = NIDMM_ATTR_BASE + Int32(126)
const NIDMM_ATTR_TEMP_THERMISTOR_C = NIDMM_ATTR_BASE + Int32(127)
const NIDMM_VAL_TYPE_NORMAL = IVI_VAL_TYPE_NORMAL
const NIDMM_VAL_TYPE_NAN = IVI_VAL_TYPE_NAN
const NIDMM_VAL_TYPE_PINF = IVI_VAL_TYPE_PINF
const NIDMM_VAL_TYPE_NINF = IVI_VAL_TYPE_NINF
const NIDMM_VAL_DC_VOLTS = IVIDMM_VAL_DC_VOLTS
const NIDMM_VAL_AC_VOLTS = IVIDMM_VAL_AC_VOLTS
const NIDMM_VAL_DC_CURRENT = IVIDMM_VAL_DC_CURRENT
const NIDMM_VAL_AC_CURRENT = IVIDMM_VAL_AC_CURRENT
const NIDMM_VAL_2_WIRE_RES = IVIDMM_VAL_2_WIRE_RES
const NIDMM_VAL_4_WIRE_RES = IVIDMM_VAL_4_WIRE_RES
const NIDMM_VAL_FREQ = IVIDMM_VAL_FREQ
const NIDMM_VAL_PERIOD = IVIDMM_VAL_PERIOD
const NIDMM_VAL_TEMPERATURE = IVIDMM_VAL_TEMPERATURE
const NIDMM_VAL_AC_VOLTS_DC_COUPLED = NIDMM_VAL_FUNC_SPECIFIC_EXT_BASE + Int32(1)
const NIDMM_VAL_DIODE = NIDMM_VAL_FUNC_SPECIFIC_EXT_BASE + Int32(2)
const NIDMM_VAL_WAVEFORM_VOLTAGE = NIDMM_VAL_FUNC_SPECIFIC_EXT_BASE + Int32(3)
const NIDMM_VAL_WAVEFORM_CURRENT = NIDMM_VAL_FUNC_SPECIFIC_EXT_BASE + Int32(4)
const NIDMM_VAL_CAPACITANCE = NIDMM_VAL_FUNC_SPECIFIC_EXT_BASE + Int32(5)
const NIDMM_VAL_INDUCTANCE = NIDMM_VAL_FUNC_SPECIFIC_EXT_BASE + Int32(6)
const NIDMM_VAL_AUTO_RANGE_ON = IVIDMM_VAL_AUTO_RANGE_ON
const NIDMM_VAL_AUTO_RANGE_OFF = IVIDMM_VAL_AUTO_RANGE_OFF
const NIDMM_VAL_AUTO_RANGE_ONCE = IVIDMM_VAL_AUTO_RANGE_ONCE
const NIDMM_VAL_AUTO_DELAY = -1.0
const NIDMM_VAL_AUTO_DELAY_ON = IVIDMM_VAL_AUTO_DELAY_ON
const NIDMM_VAL_AUTO_DELAY_OFF = IVIDMM_VAL_AUTO_DELAY_OFF
const NIDMM_VAL_IMMEDIATE = IVIDMM_VAL_IMMEDIATE
const NIDMM_VAL_EXTERNAL = IVIDMM_VAL_EXTERNAL
const NIDMM_VAL_SOFTWARE_TRIG = IVIDMM_VAL_SOFTWARE_TRIG
const NIDMM_VAL_PXI_TRIG0 = IVIDMM_VAL_TTL0
const NIDMM_VAL_PXI_TRIG1 = IVIDMM_VAL_TTL1
const NIDMM_VAL_PXI_TRIG2 = IVIDMM_VAL_TTL2
const NIDMM_VAL_PXI_TRIG3 = IVIDMM_VAL_TTL3
const NIDMM_VAL_PXI_TRIG4 = IVIDMM_VAL_TTL4
const NIDMM_VAL_PXI_TRIG5 = IVIDMM_VAL_TTL5
const NIDMM_VAL_PXI_TRIG6 = IVIDMM_VAL_TTL6
const NIDMM_VAL_PXI_TRIG7 = IVIDMM_VAL_TTL7
const NIDMM_VAL_PXI_STAR = IVIDMM_VAL_PXI_STAR
const NIDMM_VAL_LBR_TRIG1 = NIDMM_VAL_TRIGGER_SOURCE_SPECIFIC_EXT_BASE + Int32(4)
const NIDMM_VAL_AUX_TRIG1 = NIDMM_VAL_TRIGGER_SOURCE_SPECIFIC_EXT_BASE + Int32(1)
const NIDMM_VAL_NONE = IVIDMM_VAL_NONE
const NIDMM_VAL_LBR_TRIG0 = NIDMM_VAL_TRIGGER_SOURCE_SPECIFIC_EXT_BASE + Int32(3)
const NIDMM_VAL_INTERVAL = IVIDMM_VAL_INTERVAL
const NIDMM_VAL_POSITIVE = IVIDMM_VAL_POSITIVE
const NIDMM_VAL_NEGATIVE = IVIDMM_VAL_NEGATIVE
const NIDMM_VAL_TRIG_COUNT_INFINITE = 0
const NIDMM_VAL_SAMPLE_COUNT_INFINITE = 0
const NIDMM_VAL_50_HERTZ = 50.0
const NIDMM_VAL_60_HERTZ = 60.0
const NIDMM_VAL_SECONDS = IVIDMM_VAL_SECONDS
const NIDMM_VAL_POWER_LINE_CYCLES = IVIDMM_VAL_POWER_LINE_CYCLES
const NIDMM_VAL_APERTURE_TIME_AUTO = -1.0
const NIDMM_VAL_1_PLC = 1.0
const NIDMM_VAL_5_PLC = 5.0
const NIDMM_VAL_6_PLC = 6.0
const NIDMM_VAL_10_PLC = 10.0
const NIDMM_VAL_12_PLC = 12.0
const NIDMM_VAL_100_PLC = 100.0
const NIDMM_VAL_120_PLC = 120.0
const NIDMM_VAL_SETTLE_TIME_AUTO = -1.0
const NIDMM_VAL_AUTO_ZERO_AUTO = -1
const NIDMM_VAL_AUTO_ZERO_OFF = IVIDMM_VAL_AUTO_ZERO_OFF
const NIDMM_VAL_AUTO_ZERO_ON = IVIDMM_VAL_AUTO_ZERO_ON
const NIDMM_VAL_AUTO_ZERO_ONCE = IVIDMM_VAL_AUTO_ZERO_ONCE
const NIDMM_VAL_ADC_CALIBRATION_AUTO = -1
const NIDMM_VAL_ADC_CALIBRATION_OFF = 0
const NIDMM_VAL_ADC_CALIBRATION_ON = 1
const NIDMM_VAL_OFFSET_COMP_OHMS_OFF = 0
const NIDMM_VAL_OFFSET_COMP_OHMS_ON = 1
const NIDMM_VAL_1_MICROAMP = 1.0e-6
const NIDMM_VAL_10_MICROAMP = 1.0e-5
const NIDMM_VAL_100_MICROAMP = 0.0001
const NIDMM_VAL_1_MILLIAMP = 0.001
const NIDMM_VAL_DCNR_AUTO = -1
const NIDMM_VAL_DCNR_NORMAL = 0
const NIDMM_VAL_DCNR_SECOND_ORDER = 1
const NIDMM_VAL_DCNR_HIGH_ORDER = 2
const NIDMM_VAL_1_MEGAOHM = 1.0e6
const NIDMM_VAL_10_MEGAOHM = 1.0e7
const NIDMM_VAL_GREATER_THAN_10_GIGAOHM = 1.0e10
const NIDMM_VAL_RESISTANCE_NA = 0.0
const NIDMM_VAL_LATENCY_AUTO = -1
const NIDMM_VAL_BUFFER_SIZE_AUTO = -1
const NIDMM_VAL_INTERNAL_AREA = 0
const NIDMM_VAL_EXTERNAL_AREA = 1
const NIDMM_VAL_TIME_LIMIT_AUTO = -1
const NIDMM_VAL_IVIDMM_MODE = 0
const NIDMM_VAL_WAVEFORM_MODE = 1
const NIDMM_VAL_WAVEFORM_COUPLING_AC = 0
const NIDMM_VAL_WAVEFORM_COUPLING_DC = 1
const NIDMM_VAL_CALC_MODEL_AUTO = -1
const NIDMM_VAL_CALC_MODEL_SERIES = 0
const NIDMM_VAL_CALC_MODEL_PARALLEL = 1
const NIDMM_VAL_DC_BIAS_OFF = 0
const NIDMM_VAL_DC_BIAS_ON = 1
const NIDMM_VAL_CABLE_COMP_NONE = 0
const NIDMM_VAL_CABLE_COMP_OPEN = 1
const NIDMM_VAL_CABLE_COMP_SHORT = 2
const NIDMM_VAL_CABLE_COMP_OPEN_AND_SHORT = 3
const NIDMM_VAL_CONTROL_COMMIT = 0
const NIDMM_VAL_THERMOCOUPLE = IVIDMM_VAL_THERMOCOUPLE
const NIDMM_VAL_THERMISTOR = IVIDMM_VAL_THERMISTOR
const NIDMM_VAL_2_WIRE_RTD = IVIDMM_VAL_2_WIRE_RTD
const NIDMM_VAL_4_WIRE_RTD = IVIDMM_VAL_4_WIRE_RTD
const NIDMM_VAL_TEMP_REF_JUNC_FIXED = IVIDMM_VAL_TEMP_REF_JUNC_FIXED
const NIDMM_VAL_TEMP_TC_B = IVIDMM_VAL_TEMP_TC_B
const NIDMM_VAL_TEMP_TC_E = IVIDMM_VAL_TEMP_TC_E
const NIDMM_VAL_TEMP_TC_J = IVIDMM_VAL_TEMP_TC_J
const NIDMM_VAL_TEMP_TC_K = IVIDMM_VAL_TEMP_TC_K
const NIDMM_VAL_TEMP_TC_N = IVIDMM_VAL_TEMP_TC_N
const NIDMM_VAL_TEMP_TC_R = IVIDMM_VAL_TEMP_TC_R
const NIDMM_VAL_TEMP_TC_S = IVIDMM_VAL_TEMP_TC_S
const NIDMM_VAL_TEMP_TC_T = IVIDMM_VAL_TEMP_TC_T
const NIDMM_VAL_TEMP_RTD_CUSTOM = 0
const NIDMM_VAL_TEMP_RTD_PT3750 = 1
const NIDMM_VAL_TEMP_RTD_PT3851 = 2
const NIDMM_VAL_TEMP_RTD_PT3911 = 3
const NIDMM_VAL_TEMP_RTD_PT3916 = 4
const NIDMM_VAL_TEMP_RTD_PT3920 = 5
const NIDMM_VAL_TEMP_RTD_PT3928 = 6
const NIDMM_VAL_TEMP_THERMISTOR_CUSTOM = 0
const NIDMM_VAL_TEMP_THERMISTOR_44004 = 1
const NIDMM_VAL_TEMP_THERMISTOR_44006 = 2
const NIDMM_VAL_TEMP_THERMISTOR_44007 = 3
const NIDMM_EXTCAL_MISCCAL_VREF = Int32(0)
const NIDMM_EXTCAL_MISCCAL_RREF = Int32(1)
const NIDMM_EXTCAL_MISCCAL_ZINT = Int32(2)
const NIDMM_EXTCAL_MISCCAL_2WIRELEAKAGE = Int32(3)
const NIDMM_EXTCAL_MISCCAL_4WIRELEAKAGE = Int32(4)
const NIDMM_EXTCAL_MISCCAL_SECTION = Int32(5)
const NIDMM_EXTCAL_MISCCAL_VREF_DC_VOLTAGE = Int32(6)
const NIDMM_EXTCAL_MISCCAL_VREF_DC_CURRENT = Int32(7)
const NIDMM_EXTCAL_MISCCAL_VREF_AC_VOLTAGE = Int32(8)
const NIDMM_EXTCAL_MISCCAL_VREF_AC_CURRENT = Int32(9)
const NIDMM_EXTCAL_MISCCAL_VREF_RESISTANCE = Int32(10)
const NIDMM_EXTCAL_MISCCAL_VOLTAGE_AC_FILTER = Int32(11)
const NIDMM_EXTCAL_ACTION_ABORT = Int32(0)
const NIDMM_EXTCAL_ACTION_SAVE = Int32(1)
const NIDMM_EXTCAL_LC_OPEN = Int32(0)
const NIDMM_EXTCAL_LC_SHORT = Int32(1)
const NIDMM_EXTCAL_LC_25OHM = Int32(2)
const NIDMM_EXTCAL_LC_1KOHM = Int32(3)
const NIDMM_EXTCAL_LC_5KOHM = Int32(4)
const NIDMM_EXTCAL_LC_100KOHM = Int32(5)
const NIDMM_EXTCAL_LC_125OHM = Int32(6)
const NIDMM_4022_CONFIG_GUARD = Int32(0)
const NIDMM_4022_CONFIG_CURRENT_100_NANOAMP = Int32(2)
const NIDMM_4022_CONFIG_CURRENT_10_MICROAMP = Int32(3)
const NIDMM_4022_CONFIG_CURRENT_1_MILLIAMP = Int32(7)
const NIDMM_4022_CONFIG_DISCONNECT_AGND = Int32(8)


text:
function loadNeuralNet()
    path(s) = normpath("$(@__DIR__)/"*s)
    @load path("../models/agz_128_base.bson") bn
    @load path("../models/agz_128_value.bson") value
    @load path("../models/agz_128_policy.bson") policy
    @load path("../models/weights/agz_128_base.bson") bn_weights
    @load path("../models/weights/agz_128_value.bson") val_weights
    @load path("../models/weights/agz_128_policy.bson") pol_weights
    Flux.loadparams!(bn,bn_weights)
    Flux.loadparams!(value, val_weights)
    Flux.loadparams!(policy, pol_weights)
    # bn = mapleaves(cu, bn)
    # value = mapleaves(cu, value)
    # policy = mapleaves(cu, policy)
    NeuralNet(base_net = bn, value = value, policy = policy)
end

function playMove()
    move = AlphaGo.suggest_move(agz)
    println(go.to_kgs(move))
    play_move!(agz, move)
    return move
end

function playMove(x)
    move = actionToString(x)
    @show move
    play_move!(agz, go.from_kgs(move))
    return move
end

function actionToString(a)
    a["y"] == -1 && a["x"] == -1 && return "pass"
    t = (a["y"], a["x"]) .+ 1
    go.to_kgs(t)
end

function stringToAction(s, c)
    s == "pass" && return Dict("x"=>-1,"y"=>-1,"c"=>c)
    (y, x) = go.from_kgs(s) .- 1
    Dict("x"=>x,"y"=>y,"c"=>c)
end

function isIllegalMove(x)
    AlphaGo.get_position(agz) == nothing && return true
    !AlphaGo.go.is_move_legal(AlphaGo.get_position(agz), go.from_kgs(actionToString(x)))
end

# for rendering board
function updateBoard(move)
    env = Dict()
    pos = AlphaGo.get_position(agz)
    board = []
    if ( pos.board == nothing )
        board = map(i -> map(j-> [], 1:9), 1:9)
    else
        for i=1:go.N
            row = []
            for j=1:go.N
                cont = []
                if pos.board[j, i] == 1 || pos.board[j, i] == -1
                    push!(cont, Dict("x"=>(i - 1),"y"=>(j - 1),"c"=>pos.board[j, i], "type"=>"NORMAL"))
                end
                push!(row, cont)
            end
            push!(board, row)
        end
    end
    env["state"] = Dict("objects"=>board)
    env["action"] = move
    update!(gw, env)
end


text:
function anonymous_struct_tuple(data::Ptr{T}, type) where T
    vec = Vector{UInt8}(undef, sizeof(type))
    GC.@preserve vec unsafe_copyto!(pointer(vec), reinterpret(Ptr{UInt8}, data), sizeof(T))
    return type(Tuple(vec))
end

function anonymous_struct_tuple(data::Integer, type)
    raw = reinterpret(UInt8, [data])
    padded = [raw; Vector{UInt8}(undef, sizeof(type) - length(raw))]
    return type(Tuple(padded))
end

function anonymous_struct_tuple(data::UA_String, type)
    raw_length = reinterpret(UInt8, [data.length])
    raw_data = reinterpret(UInt8, [data.data])
    raw = [raw_length; raw_data]
    padded = [raw; Vector{UInt8}(undef, sizeof(type) - length(raw))]
    return type(Tuple(padded))
end

function anonymous_struct_tuple(data::UA_Guid, type)
    raw_data1 = reinterpret(UInt8, [data.data1])
    raw_data2 = reinterpret(UInt8, [data.data2])
    raw_data3 = reinterpret(UInt8, [data.data3])
    raw = [raw_data1; raw_data2; raw_data3; data.data4...]
    padded = [raw; Vector{UInt8}(undef, sizeof(type) - length(raw))]
    return type(Tuple(padded))
end


text:
module mmacousticcouplingpanelsm1
using FinEtools
using FinEtoolsAcoustics
using Test
function test()
    R = 0.5 * phun("m")
    E = 205000 * phun("MPa")
    nu = 0.3
    rho = 7850 * phun("kg/m^3");# mass density
    dummybulk, dummyrho = (1.0, 1.0)
    neigvs=6+18;
    OmegaShift=(2*pi*100.0)^2;
    nperradius = 2
    tolerance = R/10000; # geometrical tolerance

    # Construct the mesh
    r(c) = c[[1, 4, 3, 2, 5, 8, 7, 6]]
    origin = [0.0, 0.0, 0.0]
    fens,fes = H8spheren(R, nperradius); # Mesh
    fens1,fes1  =  mirrormesh(fens, fes, [-1.0, 0.0, 0.0], origin,  renumb = r);
    fens,newfes1,fes2 =  mergemeshes(fens1, fes1, fens, fes, tolerance)
    fes = cat(newfes1,fes2)
    fens1,fes1  =  mirrormesh(fens, fes, [0.0, -1.0, 0.0], origin,  renumb = r);
    fens,newfes1,fes2 =  mergemeshes(fens1, fes1, fens, fes, tolerance)
    fes = cat(newfes1,fes2)
    fens1,fes1  =  mirrormesh(fens, fes, [0.0, 0.0, -1.0], origin,  renumb = r);
    fens,newfes1,fes2 =  mergemeshes(fens1, fes1, fens, fes, tolerance)
    fes = cat(newfes1,fes2)

    # Extract the mesh of the boundary
    bfes  =  meshboundary(fes)

    # Debugging graphics
    # File  =   "Sphere.vtk"
    # vtkexportmesh(File, fes.conn, fens.xyz, MeshExportModule.H8)
    # @async run(`"paraview.exe" $File`)

    geom = NodalField(fens.xyz)
    u = NodalField(zeros(size(fens.xyz,1),3)) # displacement field

    numberdofs!(u)

    MR = DeforModelRed3D
    material = MatDeforElastIso(MR, rho, E, nu, 0.0)

    femm = FEMMDeforLinear(MR, IntegDomain(fes, GaussRule(3, 2)), material)
    associategeometry!(femm,  geom)
    # K  = stiffness(femm, geom, u)
    # M = mass(femm, geom, u)

    # d,v,nev,nconv = eigs(K+OmegaShift*M, M; nev=neigvs, which=:SM)
    # d = d .- OmegaShift;
    # fs = real(sqrt.(complex(d)))/(2*pi)
    # println("Eigenvalues: $fs [Hz]")

    femm = FEMMAcoustSurf(IntegDomain(bfes, TrapezoidalRule(2)), MatAcoustFluid(dummybulk, dummyrho))
    G = acousticcouplingpanels(femm, geom, u);
    @test abs(G[25 ,   1]  -  0.03125) / abs(0.03125) < 10e-4
    @test abs(G[31 ,   3]  -  0.0255155) / abs(0.0255155) < 10e-4
    @test abs(G[58 ,  13]  -  -0.03125) / abs(-0.03125) < 10e-4
    @test abs(G[91 ,  19]  -  -0.00810978) / abs(-0.00810978) < 10e-4
    @test abs(G[118,  22]  -  0.0105689) / abs(0.0105689) < 10e-4
    @test abs(G[159,  24]  -  -0.019781) / abs(-0.019781) < 10e-4

    true

end
end
using .mmacousticcouplingpanelsm1
mmacousticcouplingpanelsm1.test()


text:
using ComplexMixtures
using PDBTools
using Plots
using LaTeXStrings
using EasyFit

function fig() # to avoid globals

# Plot defaults
plot_font = "Computer Modern"
default(
    fontfamily=plot_font,
    linewidth=2.5,
    framestyle=:box,
    label=nothing,
    grid=false,
    palette=:tab10
)
scalefontsizes(); scalefontsizes(1.3)

# Load system PDB file
system = readPDB("./simulation/equilibrated.pdb")

# Select the atoms corresponding to glycerol and water
glyc = select(system,"resname GLLM")
water = select(system,"water")

# Set the solute structure for Glycerol, used to extract atomic contributions
solute = Selection(glyc,natomspermol=14)

# Load previously computed data
mddf_glyc = load("./results/mddf_glyc.json")
mddf_water_glyc = load("./results/mddf_water_glyc.json")

# Plot the correlation functions
plot(layout=(2,1))
x = mddf_glyc.d # distances
y = movavg(mddf_glyc.mddf,n=10).x # the mddf (using movavg to smooth noise)
plot!(x,y,label="Glycerol")
x = mddf_water_glyc.d
y = movavg(mddf_water_glyc.mddf,n=10).x
plot!(x,y,label="Water")
plot!(
    ylabel="MDDF",
    xlim=(1.5,8),subplot=1
)

# Plot the KB integrals
y = movavg(mddf_glyc.kb,n=10).x
plot!(x,y,subplot=2)
y = movavg(mddf_water_glyc.kb,n=10).x
plot!(x,y,subplot=2)
plot!(
    xlabel=L"\textrm{Distance / \AA}",ylabel=L"\textrm{KB~/~cm^3~mol^{-1}}",
    xlim=(0,20),subplot=2
)
savefig("./results/mddf_kb.png")

# Plot some group contributions to the MDDF. We select the atom names
# corresponding to each type of group of the glycerol molecule.
hydroxyls = ["O1","O2","O3","HO1","HO2","HO3"]
aliphatic = ["C1","C2","C3","H11","H12","H2","H31","H32"]

# Retrieve the contributions of these groups to the MDDFs
hydroxyl_contrib = contrib(solute,mddf_glyc.solvent_atom,hydroxyls)
aliphatic_contrib = contrib(solute,mddf_glyc.solvent_atom,aliphatic)

# Plot group contributions
plot(layout=(2,1))
x = mddf_glyc.d
y = movavg(mddf_glyc.mddf,n=10).x
plot!(x,y,label="Total",supblot=1)
y = movavg(hydroxyl_contrib,n=10).x
plot!(x,y,label="Hydroxyl contributions",subplot=1)
y = movavg(aliphatic_contrib,n=10).x
plot!(x,y,label="Aliphatic contributions",subplot=1)
plot!(
    xlim=(1,8),
    ylabel="MDDF",
    subplot=1
)

x = mddf_water_glyc.d
y = movavg(mddf_water_glyc.mddf,n=10).x
plot!(x,y,label="Total",subplot=2)
hydroxyl_contrib = contrib(solute,mddf_water_glyc.solute_atom,hydroxyls)
aliphatic_contrib = contrib(solute,mddf_water_glyc.solute_atom,aliphatic)

y = movavg(hydroxyl_contrib,n=10).x
plot!(x,y,label="Hydroxyl contributions",subplot=2)
y = movavg(aliphatic_contrib,n=10).x
plot!(x,y,label="Aliphatic contributions",subplot=2)
plot!(
    xlim=(1,8),
    xlabel=L"\textrm{Distance / \AA}",
    ylabel="MDDF",
    subplot=2
)
savefig("./results/mddf_groups.png")

# 2D maps plot of group contributions

# Glycerol groups
groups = [
    (["O1","HO1"],"OH"), # first hydroxyl
    (["C1","H11","H12"],L"\textrm{CH_2}"), # first CH2
    (["O2","HO2"],"OH"), # second hydroxyl
    (["C2","H2"],"CH"), # CH
    (["C3","H31","H32"],L"\textrm{CH_2}"), # second CH2
    (["O3","HO3"],"OH") # third hydroxyl
]

# Contributions to Glycerol-Glycerol autocorrelation
group_contrib = zeros(length(mddf_glyc.d),length(groups))
for (igroup, group) in pairs(groups)
    group_contrib[:,igroup] .= contrib(solute,mddf_glyc.solute_atom,group[1])
end

idmin = findfirst( d -> d > 1.5, mddf_glyc.d)
idmax = findfirst( d -> d > 3.0, mddf_glyc.d)
labels = [ "OH", L"\textrm{CH_2}", "OH", "CH", L"\textrm{CH_2}", "OH" ]

plot(layout=(2,1))
contourf!(
    1:length(groups),
    mddf_glyc.d[idmin:idmax],
    group_contrib[idmin:idmax,:],
    color=cgrad(:tempo),linewidth=1,linecolor=:black,
    colorbar=:none,levels=5,
    xticks=(1:length(groups),labels),xrotation=60,
    ylabel=L"r/\AA",
    subplot=1
)

# Water-glycerol interactions (Glycerol contributions)
group_contrib = zeros(length(mddf_glyc.d),length(groups))
for (igroup, group) in pairs(groups)
    group_contrib[:,igroup] .= contrib(solute,mddf_water_glyc.solute_atom,group[1])
end
contourf!(
    1:length(groups),
    mddf_glyc.d[idmin:idmax],
    group_contrib[idmin:idmax,:],
    color=cgrad(:tempo),linewidth=1,linecolor=:black,
    colorbar=:none,levels=5,
    xticks=(1:length(groups),labels),xrotation=60,
    ylabel=L"r/\AA",
    subplot=2
)
plot!(
    xlabel="Glycerol group",
    subplot=2
)

savefig("./results/map2D_glyc_glyc.png")
savefig("./results/figure3.pdf")

end; fig()


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

## dummy stub for https://github.com/JuliaBinaryWrappers/p7zip_jll.jl
baremodule p7zip_jll
using Base
Base.Experimental.@compiler_options compile=min optimize=0 infer=false

const PATH_list = String[]
const LIBPATH_list = String[]

export p7zip

# These get calculated in __init__()
const PATH = Ref("")
const LIBPATH = Ref("")
artifact_dir = ""
p7zip_path = ""
if Sys.iswindows()
    const p7zip_exe = "7z.exe"
else
    const p7zip_exe = "7z"
end

if Sys.iswindows()
    const LIBPATH_env = "PATH"
    const LIBPATH_default = ""
    const pathsep = ';'
elseif Sys.isapple()
    const LIBPATH_env = "DYLD_FALLBACK_LIBRARY_PATH"
    const LIBPATH_default = "~/lib:/usr/local/lib:/lib:/usr/lib"
    const pathsep = ':'
else
    const LIBPATH_env = "LD_LIBRARY_PATH"
    const LIBPATH_default = ""
    const pathsep = ':'
end

function adjust_ENV!(env::Dict, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    if adjust_LIBPATH
        LIBPATH_base = get(env, LIBPATH_env, expanduser(LIBPATH_default))
        if !isempty(LIBPATH_base)
            env[LIBPATH_env] = string(LIBPATH, pathsep, LIBPATH_base)
        else
            env[LIBPATH_env] = LIBPATH
        end
    end
    if adjust_PATH && (LIBPATH_env != "PATH" || !adjust_LIBPATH)
        if adjust_PATH
            if !isempty(get(env, "PATH", ""))
                env["PATH"] = string(PATH, pathsep, env["PATH"])
            else
                env["PATH"] = PATH
            end
        end
    end
    return env
end

function p7zip(f::Function; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    env = adjust_ENV!(copy(ENV), PATH[], LIBPATH[], adjust_PATH, adjust_LIBPATH)
    withenv(env...) do
        return f(p7zip_path)
    end
end
function p7zip(; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
    env = adjust_ENV!(copy(ENV), PATH[], LIBPATH[], adjust_PATH, adjust_LIBPATH)
    return Cmd(Cmd([p7zip_path]); env)
end

function init_p7zip_path()
    # Prefer our own bundled p7zip, but if we don't have one, pick it up off of the PATH
    # If this is an in-tree build, `7z` will live in `bin`.  Otherwise, it'll be in `libexec`
    for bundled_p7zip_path in (joinpath(Sys.BINDIR, Base.LIBEXECDIR, p7zip_exe),
                               joinpath(Sys.BINDIR, p7zip_exe))
        if isfile(bundled_p7zip_path)
            global p7zip_path = abspath(bundled_p7zip_path)
            return
        end
    end
    global p7zip_path = something(Sys.which(p7zip_exe), p7zip_exe)
end

function __init__()
    global artifact_dir = dirname(Sys.BINDIR)
    init_p7zip_path()
    PATH[] = dirname(p7zip_path)
    push!(PATH_list, PATH[])
    append!(LIBPATH_list, [joinpath(Sys.BINDIR, Base.LIBDIR, "julia"), joinpath(Sys.BINDIR, Base.LIBDIR)])
    LIBPATH[] = join(LIBPATH_list, pathsep)
end

# JLLWrappers API compatibility shims.  Note that not all of these will really make sense.
# For instance, `find_artifact_dir()` won't actually be the artifact directory, because
# there isn't one.  It instead returns the overall Julia prefix.
is_available() = true
find_artifact_dir() = artifact_dir
dev_jll() = error("stdlib JLLs cannot be dev'ed")
best_wrapper = nothing

end  # module p7zip_jll

max_stars_repo_name: jonas-schulze/julia

max_issues_repo_name: jonas-schulze/julia

max_forks_repo_name: jonas-schulze/julia


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

@doc raw"""HTTPIngressPath associates a path regex with a backend. Incoming urls matching the path are forwarded to the backend.

    IoK8sApiNetworkingV1beta1HTTPIngressPath(;
        backend=nothing,
        path=nothing,
    )

    - backend::IoK8sApiNetworkingV1beta1IngressBackend : Backend defines the referenced service endpoint to which the traffic will be forwarded to.
    - path::String : Path is an extended POSIX regex as defined by IEEE Std 1003.1, (i.e this follows the egrep/unix syntax, not the perl syntax) matched against the path of an incoming request. Currently it can contain characters disallowed from the conventional \"path\" part of a URL as defined by RFC 3986. Paths must begin with a '/'. If unspecified, the path defaults to a catch all sending traffic to the backend.
"""
mutable struct IoK8sApiNetworkingV1beta1HTTPIngressPath <: SwaggerModel
    backend::Any # spec type: Union{ Nothing, IoK8sApiNetworkingV1beta1IngressBackend } # spec name: backend
    path::Any # spec type: Union{ Nothing, String } # spec name: path

    function IoK8sApiNetworkingV1beta1HTTPIngressPath(;backend=nothing, path=nothing)
        o = new()
        validate_property(IoK8sApiNetworkingV1beta1HTTPIngressPath, Symbol("backend"), backend)
        setfield!(o, Symbol("backend"), backend)
        validate_property(IoK8sApiNetworkingV1beta1HTTPIngressPath, Symbol("path"), path)
        setfield!(o, Symbol("path"), path)
        o
    end
end # type IoK8sApiNetworkingV1beta1HTTPIngressPath

const _property_map_IoK8sApiNetworkingV1beta1HTTPIngressPath = Dict{Symbol,Symbol}(Symbol("backend")=>Symbol("backend"), Symbol("path")=>Symbol("path"))
const _property_types_IoK8sApiNetworkingV1beta1HTTPIngressPath = Dict{Symbol,String}(Symbol("backend")=>"IoK8sApiNetworkingV1beta1IngressBackend", Symbol("path")=>"String")
Base.propertynames(::Type{ IoK8sApiNetworkingV1beta1HTTPIngressPath }) = collect(keys(_property_map_IoK8sApiNetworkingV1beta1HTTPIngressPath))
Swagger.property_type(::Type{ IoK8sApiNetworkingV1beta1HTTPIngressPath }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_IoK8sApiNetworkingV1beta1HTTPIngressPath[name]))}
Swagger.field_name(::Type{ IoK8sApiNetworkingV1beta1HTTPIngressPath }, property_name::Symbol) =  _property_map_IoK8sApiNetworkingV1beta1HTTPIngressPath[property_name]

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

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


text:
const dt = 0.025
const SHOW_PROGRESS = false


text:
## list packages that shall be automatically loaded
module EconDatasets

using DataFrames
using TimeSeries
using Base.Dates

export dataset,
	getDataset,
	readFamaFrenchRaw,
	readUSTreasuries,
	readYahooAdjClose,
	readYahooFinance

## load interactive functions
include("readFamaFrenchRaw.jl")
include("readYahooFinance.jl")
include("readTreasuryRates.jl")

include("dataset.jl")
include("getDataset.jl")

## calls to interactive functions with fixed inputs
include("getDataset/getIndices.jl")
include("getDataset/getFFF.jl")
include("getDataset/getUMD.jl")
include("getDataset/getTreasuries.jl")
include("getDataset/getDieboldLi.jl")
include("getDataset/getIndustryPortfolios.jl")

# don't include: script would run on each startup!
## include("getDataset/getSP500.jl")
## include("getDataset/getSP500TickerSymbols.jl")

end # module


text:
# RELOG: Reverse Logistics Optimization
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.

function to_csv(graph::Graph)
    result = ""
    for a in graph.arcs
        result *= "$(a.source.index),$(a.dest.index)\n"
    end
    return result
end

max_stars_repo_name: ANL-CEEESA/RELOG

max_issues_repo_name: ANL-CEEESA/RELOG

max_forks_repo_name: ANL-CEEESA/RELOG


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

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing
        el
    end
end

# ╔═╡ 5856fdbe-c5e9-11eb-33d0-2d17b97b572c
begin
	using CSV
	using DataFrames
	using GLM
	using PlutoUI
	using Plots
end

# ╔═╡ b3b94edc-fd96-4403-bdc7-a1f5af651d6c
data = CSV.read("D:\\Workspace\\Machine Learning\\Indian GDP Analysis and Prediction\\Data\\Indian_gdp.csv",DataFrame)

# ╔═╡ e1c7d649-9922-4897-998f-f401ecb88158
scatter(data.year,data.GDP)

# ╔═╡ b2c5ec62-314f-4cd4-a7bc-b6e353c64398
reg = fit(LinearModel, @formula(GDP ~ year), data)

# ╔═╡ 97eb7071-cf68-4801-918d-53f9157a9f44
linear_regression = predict(reg)

# ╔═╡ a5de798c-aae2-452e-930b-6716c739b108
begin
	plot(data.year,linear_regression)
	scatter!(data.year,data.GDP)
end

# ╔═╡ 2fa71a79-93fa-43a8-9ee7-12fddeb5f971
md"Enter an year to predict GDP : $@bind y TextField()"

# ╔═╡ 6b671101-053c-4136-b3b7-37674655cccf
pyear = parse(Int64,y)

# ╔═╡ 22fa2415-d9d7-4c91-a235-0c94340d7f51
pGDP = coef(reg)[2]*pyear+coef(reg)[1]

# ╔═╡ Cell order:
# ╠═5856fdbe-c5e9-11eb-33d0-2d17b97b572c
# ╠═b3b94edc-fd96-4403-bdc7-a1f5af651d6c
# ╠═e1c7d649-9922-4897-998f-f401ecb88158
# ╠═b2c5ec62-314f-4cd4-a7bc-b6e353c64398
# ╠═97eb7071-cf68-4801-918d-53f9157a9f44
# ╠═a5de798c-aae2-452e-930b-6716c739b108
# ╠═2fa71a79-93fa-43a8-9ee7-12fddeb5f971
# ╠═6b671101-053c-4136-b3b7-37674655cccf
# ╠═22fa2415-d9d7-4c91-a235-0c94340d7f51

max_stars_repo_path: Indian GDP Analysis and Prediction/main.jl

max_stars_repo_name: chidhvilash/GDP-PerCapita-Analysis

max_issues_repo_name: chidhvilash/GDP-PerCapita-Analysis

max_forks_repo_name: chidhvilash/GDP-PerCapita-Analysis


text:
# ------------------------------------------------------------------
# Licensed under the ISC License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
    CrossValidation(k; shuffle=true, loss=Dict())

`k`-fold cross-validation. Optionally, `shuffle` the
data, and specify `loss` function  from `LossFunctions.jl`
for some of the variables.

    CrossValidation(partitioner; loss=Dict())

Generalization of k-fold cross-validation in which
the data is split using `partitioner`.

## References

* Geisser, S. 1975. [The predictive sample reuse method with applications]
  (https://www.jstor.org/stable/2285815)
* Burman, P. 1989. [A comparative study of ordinary cross-validation, v-fold
  cross-validation and the repeated learning-testing methods]
  (https://www.jstor.org/stable/2336116)
"""
struct CrossValidation{P<:AbstractPartitioner} <: AbstractErrorEstimator
  partitioner::P
  loss::Dict{Symbol,SupervisedLoss}
end

CrossValidation(partitioner::AbstractPartitioner; loss=Dict()) =
  CrossValidation{typeof(partitioner)}(partitioner, loss)

CrossValidation(k::Int; shuffle=true, loss=Dict()) =
  CrossValidation(UniformPartitioner(k, shuffle), loss=loss)

function error(solver::AbstractLearningSolver,
               problem::LearningProblem,
               eestimator::CrossValidation)
  # retrieve problem info
  sdata = sourcedata(problem)
  ovars = outputvars(task(problem))
  partitioner = eestimator.partitioner
  loss  = eestimator.loss
  for var in ovars
    if var ∉ keys(loss)
      loss[var] = defaultloss(sdata[var][1])
    end
  end

  # folds for cross-validation
  folds  = subsets(partition(sdata, partitioner))
  nfolds = length(folds)

  # error for a fold k
  function ε(k)
    # source and target indices
    sinds = [ind for i in [1:k-1; k+1:nfolds] for ind in folds[i]]
    tinds = folds[k]

    # source and target data
    train = view(sdata, sinds)
    hold  = view(sdata, tinds)

    # setup and solve sub-problem
    subproblem = LearningProblem(train, hold, task(problem))
    solution   = solve(subproblem, solver)

    # loss for each variable
    losses = map(ovars) do var
      y = hold[var]
      ŷ = solution[var]
      ℒ = value(loss[var], y, ŷ, AggMode.Mean())
      var => ℒ
    end

    Dict(losses)
  end

  # compute error for each fold in parallel
  εs = foldxt(vcat, Map(ε), 1:nfolds)

  # combine error from different folds
  Dict(var => mean(get.(εs, var, 0)) for var in ovars)
end


text:
function ACQR_ksmoother(A,xtt,Ptt,xtt1,Ptt1)
	#
	# Kalman smoother for model
	#
	# x_{t+1} = Ax_{t} + w_{t}
	# y_{t}   = Cx_{t} + v_{t}
	#
	# cov(w_{t},v_{t}) = [Q 0;0 R]
	#
	# javier.cara@upm.es, 2016-02
	#

	nx,nt = size(xtt)

	# allocation
	xtN = zeros(nx,nt+1)
	PtN = zeros(nx,nx,nt+1)
	Pt1tN = zeros(nx,nx,nt)

	# values for t = nt+1
	xtN[:,nt+1] = xtt1[:,nt+1]
	PtN[:,:,nt+1] = Ptt1[:,:,nt+1]

	# values for t=nt
	xtN[:,nt] = xtt[:,nt]
	PtN[:,:,nt] = Ptt[:,:,nt]
	Pt1tN[:,:,nt] = A*Ptt[:,:,nt]

	# smother
	for t = nt-1:-1:1
		# Kalman Smoother matrix J
		Jt = (Ptt[:,:,t]*A') / Ptt1[:,:,t+1]

		xtN[:,t] = xtt[:,t] + Jt*( xtN[:,t+1] - xtt1[:,t+1] )
		PtN[:,:,t] = Ptt[:,:,t] + Jt*( PtN[:,:,t+1] - Ptt1[:,:,t+1] )*Jt'

		Pt1tN[:,:,t] = PtN[:,:,t+1]*Jt'
	end

	return xtN,PtN,Pt1tN

end


text:
using Documenter, ActiveNetworkManagement

makedocs(
    format = :html,
    sitename = "ActiveNetworkManagement.jl",
    pages = [
    "Summary" => "index.md",
    "MDP and model" => "markov.md",
    "Reinforcement learning" => "rl.md",
    "Multi-time-steps optimization" => "opti.md",
    ]
)

max_stars_repo_name: qlete/ANManagement

max_issues_repo_name: qlete/ANManagement

max_forks_repo_name: qlete/ANManagement


text:
# MonoidAlternative
# =================

a = Writer("a", [1])
b = Writer("b", [2,3,4])

# monoid is supported for convenience
a ⊕ b == Writer("ab", [1,2,3,4])

# FunctorApplicativeMonad
# =======================

@test eltype(Writer{Int, String}) == String

@test map(x -> [x; x], a) == Writer("a", [1,1])

product_ab = Writer("ab", [1,2,3,4])
@test mapn(a, b) do x, y
  [x; y]
end == product_ab

h = @syntax_flatmap begin
  x = a
  y = b
  @pure [x; y]
end
@test h == product_ab

@test pure(Writer{String}, 3) == Writer("", 3)

# working with TypeClasses.pure
@test (@syntax_flatmap begin
  a = pure(Writer{String}, 5)
  Writer("hi")
  @pure a
end) == Writer("hi", 5)

@test (@syntax_flatmap begin
  a = pure(Writer, 5)
  Writer(Option("hi"))
  @pure a
end) == Writer(Option("hi"), 5)

@test (@syntax_flatmap begin
  a = pure(Writer, 5)
  Writer("hi")
  @pure a
end) == Writer("hi", 5)

# FlipTypes
# =========

v = Writer("first", [:a, :b, :c])
@test flip_types(v) == [Writer("first", :a), Writer("first", :b), Writer("first", :c)]

vs = [Writer("first", :a), Writer("second", :b), Writer("third", :c)]
@test flip_types(vs) == Writer("firstsecondthird", [:a, :b, :c])


text:
struct Rectangle
    x::Number
    y::Number
    w::Number
    h::Number
end

Base.:(==)(lhs::Rectangle, rhs::Rectangle) = lhs.x == rhs.x && lhs.y == rhs.y && lhs.w == rhs.w && lhs.h == rhs.h

# AABB check
function checkCollision(box1::Rectangle, box2::Rectangle)
    return (
        box1.x < box2.x + box2.w &&
        box1.x + box1.w > box2.x &&
        box1.y < box2.y + box2.h &&
        box1.y + box1.h > box2.y
    )
end

function intersection(box1::Rectangle, box2::Rectangle)
    x = max(box1.x, box2.x)
    y = max(box1.y, box2.y)
    w = min(box1.x + box1.w, box2.x + box2.w) - x
    h = min(box1.y + box1.h, box2.y + box2.h) - y
    return w > 0 && h > 0 ? Rectangle(x, y, w, h) : nothing
end

# Find top left corner and bottom right corner
function bounds(rects::Array{Rectangle, 1})
    tlx = tly = typemax(Int)
    brx = bry = typemin(Int)

    for rect in rects
        tlx = min(tlx, rect.x)
        tly = min(tly, rect.y)

        brx = max(brx, rect.x + rect.w)
        bry = max(bry, rect.y + rect.h)
    end

    return tlx, tly, brx, bry
end

# Rectangle that covers all input rectangles
function coverRectangles(rects::Array{Rectangle, 1})
    tlx, tly, brx, bry = bounds(rects)

    return Rectangle(tlx, tly, brx - tlx, bry - tly)
end


text:
println("# Julia says welcome from node ",gethostname() )

# Functions for demo calculation
function calc_pi(N::Integer)
  piapprox = 0.0
  for i in 1:N
    x, y = rand(), rand()
    piapprox += (x*x+y*y <= 1.0) ? 1.0 : 0.0
  end
  piapprox *= 4.0/N
end

# Perform demo calculation
srand(42)        # seed random number generator for repeatability
calc_pi(10)      # a test run to make sure it compiles before we start timing it
@time piapprox = calc_pi(100000000)
@printf("pi is estimated to be %14.12f\n", piapprox)


text:
import JSON
using GitLab, GitLab.name, GitLab.GitLabString, GitLab.Branch
using Base.Test

# This file tests various GitLabType constructors. To test for proper Nullable
# handling, most fields have been removed from the JSON samples used below.
# Sample fields were selected in order to cover the full range of type behavior,
# e.g. if the GitLabType has a few Nullable{Dates.DateTime} fields, at least one
# of those fields should be present in the JSON sample.

function test_show(g::GitLab.GitLabType)
    tmpio = IOBuffer()
    show(tmpio, g)

    # basically trivial, but proves that things aren't completely broken
    @test repr(g) == takebuf_string(tmpio)

    tmpio = IOBuffer()
    showcompact(tmpio, g)

    @test "$(typeof(g))($(repr(name(g))))" == takebuf_string(tmpio)
end

#########
# Owner #
#########

owner_json = JSON.parse(
"""
{
  "name": "octocat_name",
  "username": "octocat",
  "id": 1,
  "state": "active",
  "web_url": "https://GitHub.com/octocat",
  "avatar_url": "",
  "ownership_type": "User"
}
"""
)

owner_result = Owner(
    Nullable{GitLabString}(GitLabString(owner_json["name"])),
    Nullable{GitLabString}(GitLabString(owner_json["username"])),
    Nullable{Int}(Int(owner_json["id"])),
    Nullable{GitLabString}(GitLabString(owner_json["state"])),
    Nullable{HttpCommon.URI}(HttpCommon.URI("")),
    Nullable{HttpCommon.URI}(HttpCommon.URI(owner_json["web_url"])),
    Nullable{GitLabString}(GitLabString(owner_json["ownership_type"]))
)

@test Owner(owner_json) == owner_result
@test name(Owner(owner_json["username"])) == name(owner_result)
## @test setindex!(GitLab.gitlab2json(owner_result), nothing, "username") == owner_json
@test setindex!(GitLab.gitlab2json(owner_result), "", "avatar_url") == owner_json

test_show(owner_result)

########
# Repo #
########

repo_json = JSON.parse(
"""
{
    "project_id": 1296269,
    "owner": {
        "username": "octocat"
    },
    "name": "octocat/Hello-World",
    "public": true,
    "web_url": "https://api.github.com/repos/octocat/Hello-World",
    "last_activity_at": "2011-01-26T19:06:43"
    }
"""
)

repo_result = Repo(
    Nullable{GitLabString}(GitLabString(repo_json["name"])),
    Nullable{Int}(),
    Nullable{HttpCommon.URI}(),
    Nullable{HttpCommon.URI}(),
    Nullable{GitLabString}(),
    Nullable{Int}(Int(repo_json["project_id"])),
    Nullable{Int}(),
    Nullable{GitLabString}(),
    Nullable{Vector{GitLabString}}(),
    Nullable{Bool}(Bool(repo_json["public"])),
    Nullable{Bool}(),
    Nullable{HttpCommon.URI}(),
    Nullable{HttpCommon.URI}(HttpCommon.URI(repo_json["web_url"])),
    Nullable{Owner}(Owner(repo_json["owner"])),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(),
    Nullable{Bool}(),
    Nullable{Bool}(),
    Nullable{Bool}(),
    Nullable{Bool}(),
    Nullable{Bool}(),
    Nullable{Bool}(),
    Nullable{Dates.DateTime}(),
    Nullable{Dates.DateTime}(Dates.DateTime(repo_json["last_activity_at"])),
    Nullable{Bool}(),
    Nullable{Int}(),
    Nullable{HttpCommon.URI}(),
    Nullable{Int}(),
    Nullable{Int}(),
    Nullable{Int}(),
    Nullable{GitLabString}(),
    Nullable{Bool}()
)

@test Repo(repo_json) == repo_result
@test name(Repo(repo_json["name"])) == name(repo_result)
## @test setindex!(GitLab.gitlab2json(repo_result), nothing, "avatar_url") == repo_json

test_show(repo_result)

##########
# Commit #
##########

commit_json = JSON.parse(
"""
{
    "id": "5c35ae1de7f6d6bfadf0186e165f7af6537e7da8",
    "short_id": "5c35ae1d",
    "title": "Fixed test",
    "author_name": "Pradeep Mudlapur",
    "author_email": "pradeep@juliacomputing.com",
    "created_at": "2016-07-21T12:40:40.000+05:30",
    "message": "Fixed test"
}
"""
)

commit_result = Commit(
    Nullable{GitLabString}(GitLabString(commit_json["id"])),
    Nullable{GitLabString}(GitLabString(commit_json["author_email"])),
    Nullable{GitLabString}(GitLabString(commit_json["title"])),
    Nullable{GitLabString}(GitLabString(commit_json["short_id"])),
    Nullable{GitLabString}(GitLabString(commit_json["message"])),
    Nullable{GitLabString}(),
    Nullable{Vector{Any}}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(GitLabString(commit_json["author_name"])),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(GitLabString(commit_json["created_at"]))
)

@test Commit(commit_json) == commit_result
@test name(Commit(commit_json["id"])) == name(commit_result)
## @test setindex!(GitLab.gitlab2json(commit_result), nothing, "html_url") == commit_json

test_show(commit_result)

##########
# Branch #
##########

branch_json = JSON.parse(
"""
{
    "name": "branch1",
    "protected": false,
    "commit": {
      "id": "1c5008fbc343f8793055d155af2e760fc3c1b6be",
      "message": "test",
      "parent_ids": [
        "15b89b7edde90eabc33580799277cbed6d3e4331"
      ],
      "authored_date": "2016-07-15T17:26:55.000+05:30",
      "author_name": "Pradeep Mudlapur",
      "author_email": "pradeep@juliacomputing.com",
      "committed_date": "2016-07-15T17:26:55.000+05:30",
      "committer_name": "Pradeep Mudlapur",
      "committer_email": "pradeep@juliacomputing.com"
    }
}
"""
)

branch_result = Branch(
    Nullable{GitLabString}(GitLabString(branch_json["name"])),
    Nullable{Bool}(Bool(branch_json["protected"])),
    Nullable{Commit}(Commit(branch_json["commit"]))
)

@test Branch(branch_json) == branch_result
@test name(Branch(branch_json["name"])) == name(branch_result)
## @test setindex!(GitLab.gitlab2json(branch_result), true, "protected") == branch_json

test_show(branch_result)

###########
# Comment #
###########

comment_json = JSON.parse(
"""
{
    "note": "Test ...",
    "author": {
      "name": "Pradeep",
      "username": "mdpradeep",
      "id": 2,
      "state": "active",
      "avatar_url": "http://www.gravatar.com/avatar/7e32a35a20817e0258e12665c9099422?s=80&d=identicon",
      "web_url": "http://104.197.141.88/u/mdpradeep"
    },
    "created_at": "2016-07-16T16:02:12.923Z"
}
"""
)

comment_result = Comment(
    Nullable{GitLabString}(),
    Nullable{GitLabString}(GitLabString(comment_json["created_at"])),
    Nullable{Int64}(),
    Nullable{GitLabString}(GitLabString(comment_json["note"])),
    Nullable{Owner}(Owner(comment_json["author"])),
    Nullable{Int64}(),
    Nullable{GitLabString}(),
    Nullable{Int64}(),
    Nullable{GitLabString}(),
    Nullable{Bool}(),
    Nullable{HttpCommon.URI}(),
    Nullable{Bool}(),
    Nullable{GitLabString}(),
    Nullable{Int64}(),
    Nullable{GitLabString}(),
    Nullable{Int64}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}()
)

@test Comment(comment_json) == comment_result
## @test name(Comment(comment_json["id"])) == name(comment_result)
## @test setindex!(GitLab.gitlab2json(comment_result), nothing, "position") == comment_json

## TODO check this failure
## test_show(comment_result)

###########
# Content #
###########

content_json = JSON.parse(
"""
{
  "file_name": "file1",
  "file_path": "src/file1",
  "size": 52,
  "encoding": "base64",
  "content": "bmV3IGZpbGUKCmNoYW5nZQpjb21tZW50cwptb3JlIGNoYW5nZXMKbW9yZSBjaGFuZ2VzCg==",
  "ref": "master",
  "blob_id": "cce7fdffea49a72ec48b8055faa52a664f91b917",
  "commit_id": "5c35ae1de7f6d6bfadf0186e165f7af6537e7da8",
  "last_commit_id": "078beb463b6a21ff97fc1b93594f1e7063cd78da"
}
"""
)

content_result = Content(
    Nullable{GitLabString}(GitLabString(content_json["file_name"])),
    Nullable{GitLabString}(GitLabString(content_json["file_path"])),
    Nullable{Int}(Int(content_json["size"])),
    Nullable{GitLabString}(GitLabString(content_json["encoding"])),
    Nullable{GitLabString}(GitLabString(content_json["content"])),
    Nullable{GitLabString}(GitLabString(content_json["ref"])),
    Nullable{GitLabString}(GitLabString(content_json["blob_id"])),
    Nullable{GitLabString}(GitLabString(content_json["commit_id"])),
    Nullable{GitLabString}(GitLabString(content_json["last_commit_id"]))
)

@test Content(content_json) == content_result
@test name(Content(content_json["file_path"])) == name(content_result)
## @test setindex!(GitLab.gitlab2json(content_result), nothing, "encoding") == content_json

test_show(content_result)

##########
# Status #
##########

status_json = JSON.parse(
"""
{
    "id": 31696,
    "sha": "5c35ae1de7f6d6bfadf0186e165f7af6537e7da8",
    "ref": "",
    "status": "pending",
    "name": "default",
    "target_url": null,
    "description": null,
    "created_at": "2016-07-26T08:23:49",
    "started_at": null,
    "finished_at": null,
    "allow_failure": false,
    "author": {
      "name": "Pradeep",
      "username": "mdpradeep",
      "id": 2,
      "state": "active",
      "avatar_url": "http://www.gravatar.com/avatar/7e32a35a20817e0258e12665c9099422?s=80&d=identicon",
      "web_url": "http://104.197.141.88/u/mdpradeep"
    }
}
"""
)

status_result = Status(
    Nullable{Int}(Int(status_json["id"])),
    Nullable{Int}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(),
    Nullable{GitLabString}(GitLabString(status_json["sha"])),
    Nullable{HttpCommon.URI}(),
    Nullable{HttpCommon.URI}(),
    Nullable{Dates.DateTime}(Dates.DateTime(status_json["created_at"])),
    Nullable{Dates.DateTime}(),
    Nullable{Owner}(),
    Nullable{Repo}(),
    Nullable{Vector{Status}}(),
    Nullable{GitLabString}(GitLabString(status_json["status"])),
    Nullable{GitLabString}(GitLabString(status_json["name"])),
    Nullable{Owner}(Owner(status_json["author"])),
    Nullable{GitLabString}(GitLabString(status_json["ref"])),
    Nullable{Dates.DateTime}(),
    Nullable{Dates.DateTime}(),
    Nullable{Bool}(Bool(status_json["allow_failure"]))
)

@test Status(status_json) == status_result
@test name(Status(status_json["id"])) == name(status_result)
## @test setindex!(GitLab.gitlab2json(status_result), nothing, "context") == status_json

test_show(status_result)

###############
# PullRequest #
###############

pr_json = JSON.parse(
"""
  {
    "id": 4,
    "iid": 4,
    "project_id": 1,
    "title": "test",
    "description": "",
    "state": "merged",
    "created_at": "2016-07-15T11:58:01.819",
    "updated_at": "2016-07-22T07:32:20.149",
    "target_branch": "master",
    "source_branch": "branch1",
    "upvotes": 0,
    "downvotes": 0,
    "author": {
      "name": "Administrator",
      "username": "siteadmin",
      "id": 1,
      "state": "active",
      "avatar_url": "http://www.gravatar.com/avatar/a3918c0a2d98a6606bd787c54e6e5268?s=80&d=identicon",
      "web_url": "http://104.197.141.88/u/siteadmin"
    },
    "assignee": null,
    "source_project_id": 1,
    "target_project_id": 1,
    "labels": [],
    "work_in_progress": false,
    "milestone": null,
    "merge_when_build_succeeds": false,
    "merge_status": "cannot_be_merged",
    "subscribed": true,
    "user_notes_count": 70
  }
"""
)

pr_result = PullRequest(
    Nullable{Int}(Int(pr_json["id"])),
    Nullable{Int}(Int(pr_json["iid"])),
    Nullable{Int}(Int(pr_json["project_id"])),
    Nullable{GitLabString}(GitLabString(pr_json["title"])),
    Nullable{GitLabString}(GitLabString(pr_json["description"])),
    Nullable{GitLabString}(GitLabString(pr_json["state"])),
    Nullable{Dates.DateTime}(Dates.DateTime(pr_json["created_at"])),
    Nullable{Dates.DateTime}(Dates.DateTime(pr_json["updated_at"])),
    Nullable{GitLabString}(GitLabString(pr_json["target_branch"])),
    Nullable{GitLabString}(GitLabString(pr_json["source_branch"])),
    Nullable{Int}(Int(pr_json["upvotes"])),
    Nullable{Int}(Int(pr_json["downvotes"])),
    Nullable{Owner}(Owner(pr_json["author"])),
    Nullable{Owner}(), ## assignee
    Nullable{Int}(Int(pr_json["source_project_id"])),
    Nullable{Int}(Int(pr_json["target_project_id"])),
    Nullable{Vector{GitLabString}}(Vector{GitLabString}(pr_json["labels"])),
    Nullable{Bool}(Bool(pr_json["work_in_progress"])),
    Nullable{GitLabString}(), ## milestone
    Nullable{Bool}(Bool(pr_json["merge_when_build_succeeds"])),
    Nullable{GitLabString}(GitLabString(pr_json["merge_status"])),
    Nullable{Bool}(Bool(pr_json["subscribed"])),
    Nullable{Int}(Int(pr_json["user_notes_count"]))
)

@test PullRequest(pr_json) == pr_result
@test name(PullRequest(pr_json["id"])) == name(pr_result)
## @test GitLab.gitlab2json(pr_result) == pr_json

test_show(pr_result)

#########
# Issue #
#########

issue_json = JSON.parse(
"""
{
  "id": 1,
  "iid": 1,
  "project_id": 1,
  "title": "Test Issue 1",
  "description": "Test for webhooks ...",
  "state": "opened",
  "created_at": "2016-06-20T10:06:27.980",
  "updated_at": "2016-07-26T09:37:12.651",
  "labels": [
    "MyLabel"
  ],
  "milestone": null,
  "assignee": {
    "name": "Pradeep",
    "username": "mdpradeep",
    "id": 2,
    "state": "active",
    "avatar_url": "http://www.gravatar.com/avatar/7e32a35a20817e0258e12665c9099422?s=80&d=identicon",
    "web_url": "http://104.197.141.88/u/mdpradeep"
  },
  "author": {
    "name": "Pradeep",
    "username": "mdpradeep",
    "id": 2,
    "state": "active",
    "avatar_url": "http://www.gravatar.com/avatar/7e32a35a20817e0258e12665c9099422?s=80&d=identicon",
    "web_url": "http://104.197.141.88/u/mdpradeep"
  },
  "subscribed": true,
  "user_notes_count": 12
}
"""
)

issue_result = Issue(
    Nullable{Int}(Int(issue_json["id"])),
    Nullable{Int}(Int(issue_json["iid"])),
    Nullable{Int}(Int(issue_json["project_id"])),
    Nullable{GitLabString}(GitLabString(issue_json["title"])),
    Nullable{GitLabString}(GitLabString(issue_json["description"])),
    Nullable{GitLabString}(GitLabString(issue_json["state"])),
    Nullable{Dates.DateTime}(Dates.DateTime(issue_json["created_at"])),
    Nullable{Dates.DateTime}(Dates.DateTime(issue_json["updated_at"])),
    Nullable{Vector{GitLabString}}(Vector{GitLabString}(issue_json["labels"])),
    Nullable{GitLabString}(), ## milestone
    Nullable{Owner}(Owner(issue_json["assignee"])),
    Nullable{Owner}(Owner(issue_json["author"])),
    Nullable{Bool}(Bool(issue_json["subscribed"])),
    Nullable{Int}(Int(issue_json["user_notes_count"]))
)

@test Issue(issue_json) == issue_result
@test name(Issue(issue_json["id"])) == name(issue_result)
## @test setindex!(GitLab.gitlab2json(issue_result), nothing, "closed_at") == issue_json

test_show(issue_result)


text:
include("load_data.jl")
#function for the cycle
function nxt(t,TB,TE)
    if t< TE
        return t+1
    end
    if t>= TE
        return TB
    end
end

#Model
m=Model(Gurobi.Optimizer)

#decision variables
@variable(m, pG[G,TT]>=.0);#power output of gnereator g in period t
@variable(m, pHS_h[HS,TT]>=.0); #electricity power used to generate hs at the start of period t
@variable(m, pHS_c[HS,TT]>=.0); #electricity power used to cooler heat store hs
@variable(m, pHS_plus[HS,TT]>=.0); #heat power input to heat store
@variable(m, qHS[HS,TT]>=.0); #energy in heat store hs at the start of period t
@variable(m, tInt[HS,TT]>=.0); #interior temperature of heat store hs at the start of period t
@variable(m, pES_plus[ES,TT]>=.0); #power into store es during period t
@variable(m, pES_minus[ES,TT]>=.0); #power out of store es during period t
@variable(m, qES[ES,TT]>=.0); #level of energy at the start of period t
@variable(m, pGShed[B,TT]>=.0); #generation shed at period t at bus b
@variable(m, pLShed[B,TT]>=.0); #load shed at period t at bus b
@variable(m, pl[L,TT]); #power flow into line
@variable(m, delta[B,TT]); #phase angle

#variable for planning model
@variable(m, pGmax[G]>=.0); #capacities of gnereators
@variable(m, pES_plus_cap[ES]>=.0); #maximum power into electricity store es
@variable(m, pES_minus_cap[ES]>=.0); #maximum power out of electricity store es
@variable(m, qES_plus_cap[ES]>=.0); #maixmum level of storage of electricity store es
@variable(m, plmax[L]>=.0); #line limit of line l
@variable(m, pW_cap[W]>=.0); #installed wind capacity
@variable(m, pS_cap[S]>=.0); #installed soalr capacity
@variable(m, pHS_plus_cap[HS]>=.0); #maximum input power in heat store hs

#constraints
#conventional generator limits
@constraint(m, con_limit[g in G, s in SS, t in TT[:,s]], pG[g,t]<=PGmax[g]);

#renewable generator limits and demand at each bus
PGS = [2.5*pGS_15[t] for t in T for s in S]; #solar power available
pGW1 = [WF[:,w].*Wcap_15[w] for w in W];
PGW = hcat(pGW1[1],pGW1[2],pGW1[3],pGW1[4],pGW1[5]); #wind power avaiable in each region
hp = [30*pGS_15[t] for t in T]; #heating power from solar in 2015
PD = [TPD[t]*BF[b] for t in T, b in B]; #demand of bus b in period t

#electricity store
@constraint(m, ES_balance[es in ES, s in SS, t in TT[:,s]], qES[es,nxt(t, TT[1,s], TT[end,s])]==qES[es,t]+
Ht*(EES[es]*pES_plus[es,t]-pES_minus[es,t]));
@constraint(m, ES_input_limit[es in ES, s in SS, t in TT[:,s]], pES_plus[es,t]<=PES_plus_cap[es]);
@constraint(m, ES_output_limit[es in ES, s in SS, t in TT[:,s]], pES_minus[es,t]<=PES_minus_cap[es]);
@constraint(m, ES_energy_limit[es in ES, s in SS, t in TT[:,s]], qES[es,t] <= ES_Ecap[es]);

#heating store constraint
lambda = Ploss/Qmass
@constraint(m, HS_balance[hs in HS, s in SS, t in TT[:,s]], qHS[hs,nxt(t,TT[1,s],TT[end,s])]==exp(-lambda*Ht)*qHS[hs,t]+
((EHS_h[hs]*pHS_h[hs,t]+Ploss*TExt[t]+hp[t]-EHS_c[hs]*pHS_c[hs,t])/lambda)-
exp(-lambda*Ht)*((EHS_h[hs]*pHS_h[hs,t]+Ploss*TExt[t]+hp[t]-EHS_c[hs]*pHS_c[hs,t])/lambda));
@constraint(m, Heat_pump_power[hs in HS, s in SS, t in TT[:,s]], pHS_c[hs,t]<=PHS_plus_cap[hs]);
@constraint(m, HS_temp1[hs in HS, s in SS, t in TT[:,s]], tInt[hs,t]==qHS[hs,t]/Qmass);
@constraint(m, HS_temp2[hs in HS, s in SS, t in TT[:,s]], tInt[hs,t]>=THS_minus[hs]);
@constraint(m, HS_temp3[hs in HS, s in SS, t in TT[:,s]], tInt[hs,t]<=THS_plus[hs]);

#KCL
@constraint(m, KCL[ss in SS, t in TT[:,ss], b in B], sum(pG[g,t] for g in G if GLoc[g]==b) +
sum(PGW[t,w] for w in W if WLoc[w]==b) + sum(PGS[t,s] for s in S if SLoc[s]==b) + sum(a[b,l]*pl[l,t] for l in L) +pLShed[b,t]
+sum(pES_minus[es,t] for es in ES if ESLoc[es]==b)
==PD[t,b]+pGShed[b,t]+sum(pES_plus[es,t] for es in ES if ESLoc[es]==b)+sum(pHS_h[hs,t]+pHS_c[hs,t] for hs in HS if HSLoc[hs]==b))

#network constraint
@constraint(m, rebus[s in SS, t in TT[:,s]], delta[Re_bus,t]==0);
@constraint(m, KVL[l in L, s in SS, t in TT[:,s]], pl[l,t]==(-1/LR[l])*(sum(a[b,l]*delta[b,t] for b in B)));
@constraint(m, line_limit1[l in L, s in SS, t in TT[:,s]], pl[l,t]<=PLmax[l]);
@constraint(m, line_limit2[l in L, s in SS, t in TT[:,s]], pl[l,t]>=-PLmax[l]);

#CO2 emission
CO2E = [sum(((EM[g]*pG[g,t]*Ht)/EG[g])/H for g in G for t in TT[:,s]) for s in SS];
#weighted average hourly CO2 emission
weighted_CO2E = sum(WS[s]*CO2E[s] for s in SS);
# @constraint(m, CO2emission, weighted_CO2E<=CO2_max);

#CAPEX
# generator_capex = sum(((FG_CPX[g]/YG[g])+FG_OM[g])*pGmax[g]/Y for g in G)
# wind_capex = sum(((FW_CPX[w]/YW[w])+FW_OM[w])*pW_cap[w]/Y for w in W)
# solar_capex = sum((((FS_CPX[s]/YS[s])+FS_OM[s])*pS_cap[s])/Y for s in S)
# HS_capex = sum(((FHS_CPX[hs]/YHS[hs])+FHS_OM[hs])*pHS_plus_cap[hs]/Y for hs in HS)
# ES_capex = sum(((FES_CPX[es]/YES[es])+FES_OM[es])*pES_plus_cap[es]/Y for es in ES)
# ESE_capex = sum(((FES_ECPX[es]/YES[es]))*qES_plus_cap[es]/Y for es in ES)
# line_capex = sum(((FL_CPX[l]/YL[l])+FL_OM[l])*plmax[l]/Y for l in L)
# CAPEX = generator_capex+wind_capex+solar_capex+HS_capex+ES_capex+ESE_capex+line_capex;

#OPEX
operational_cost = [sum(((CG[g]*pG[g,t]*Ht)/H) for g in G for t in TT[:,s]) for s in SS];
fuel_cost = [sum((CFuel[g]*pG[g,t]/EG[g]*Ht)/H for g in G for t in TT[:,s]) for s in SS];
CO2_cost = [sum((CO2_tax*EM[g]*pG[g,t]*Ht/EG[g])/H for g in G for t in TT[:,s]) for s in SS];
GShed_cost = [sum(CShed_gen*pGShed[b,t]*Ht/H for t in TT[:,s] for b in B) for s in SS];
LShed_cost = [sum(CShed_load*pLShed[b,t]*Ht/H for t in TT[:,s] for b in B) for s in SS];
ES_cost = [sum(((CElect[es]*pES_plus[es,t]*Ht)/H) for es in ES for t in TT[:,s]) for s in SS];
HS_cost = [sum(CHeat[hs]*(pHS_h[hs,t]+pHS_c[hs,t])*Ht/H for t in TT[:,s] for hs in HS) for s in SS];
O= hcat(operational_cost, fuel_cost, CO2_cost, GShed_cost, LShed_cost, ES_cost,HS_cost);
OPEX = sum(((operational_cost[s]+fuel_cost[s]+CO2_cost[s]+GShed_cost[s]+LShed_cost[s]+ES_cost[s]
+HS_cost[s])*WS[s]) for s in SS);

@objective(m, Min, OPEX)

optimize!(m)

# open("planning reslut.txt","w") do io
#
#     println(io,"CAPEX:", value.(CAPEX))
#     println(io, "OPEX:", value.(OPEX))
#     for g in G
#         println(io, "Capacity of ", g, " " , value.(pGmax[g]))
#     end
#     for w in W
#         println(io, "Capacity of wind farm", w, " ", value.(pW_cap[w]))
#     end
#     for s in S
#         println(io, "Capacity of solar PV", s, " ", value.(pS_cap[s]))
#     end
#     println(io, "CO2 emission"," ", value.(weighted_CO2E))
#     for es in ES
#         println(io,"Input electric power capacity", " ", value.(pES_plus_cap[es]))
#         println(io, "PHSE storage capacity" , " ", value.(qES_plus_cap[es]))
#     end
#     for hs in HS
#         println(io, "Input power of heat store", " ", value.(pHS_plus_cap[hs]))
#     end
#     #println(io, "CO2 marginal cost", " ", dual.(CO2emission))
#     for l in L
#         println(io, "line capacity of ", " ",l,": ", value.(plmax[l]))
#     end
# end
#
#
# open("plot reslut.csv","w") do io
#             for t in TT[:,1]
#                     println(io,t,",", value.(pG[4,t]),",",value.(pG[4,t]+pG[3,t]),",",
#                     value.(pG[4,t]+pG[3,t]+pG[2,t]),",",value.(pG[4,t]+pG[3,t]+pG[2,t]+pG[1,t]),",",
#                     value.(pG[4,t]+pG[3,t]+pG[2,t]+pG[1,t]+sum(pGW[t,w] for w in W)),",",
#                     value.(pG[4,t]+pG[3,t]+pG[2,t]+pG[1,t]+sum(pGW[t,w] for w in W)+pGS[t,1]),","
#                     ,sum(PD[t,b] for b in B),","
#                     ,sum(PD[t,b] for b in B)+value.(pHS_h[1,t]))
#             end
# end
#
# open("wind reslut.csv","w") do io
#             for t in TT[:,3]
#                     println(io,t,",", value.(pGW[t,1]),",",value.(pGW[t,2]),",", value.(pGW[t,3]),",",
#                     value.(pGW[t,4]),",",value.(pGW[t,5]))
#             end
# end

max_stars_repo_path: Operational model.jl

max_issues_repo_path: Operational model.jl

max_forks_repo_path: Operational model.jl


text:
abstract type InitializationStrategy end

# TODO: base this on the existence of a velocity gradient, pressure and velocity
# InitializationStrategy(problem::FluidFlowProblem) = AnalyticalEquilibriumAndOffEquilibrium()
InitializationStrategy(problem::FluidFlowProblem) = AnalyticalEquilibrium()

function initialize(
    strategy::InitializationStrategy,
    q::Quadrature,
    problem::FluidFlowProblem,
    cm = SRT,
)
    f = Array{eltype(q.weights)}(undef, problem.NX, problem.NY, length(q.weights))

    x_range, y_range = range(problem)
    for x_idx in 1:(problem.NX), y_idx in 1:(problem.NY)
        f[x_idx, y_idx, :] =
            initial_condition(strategy, q, problem, x_range[x_idx], y_range[y_idx])
    end

    return f
end
initial_condition(
    strategy::InitializationStrategy,
    q::Quadrature,
    problem::FluidFlowProblem,
    x::T,
    y::T,
) where {T <: Real} = initial_condition(q, problem, x, y)

include("initial_conditions/constant_density.jl")
include("initial_conditions/analytical_equilibrium.jl")
include("initial_conditions/analytical_offequilibrium.jl")
include("initial_conditions/analytical_velocity.jl")
include("initial_conditions/analytical_velocity_stress.jl")
include("initial_conditions/mei_et_al.jl")

"""
f₀(x) = f_eq(ρ₀, u₀, p₀)
ρ₀ = 1.0
u₀ = 0.0
p₀ = 1.0
"""
struct ZeroVelocityInitialCondition <: InitializationStrategy end
function initial_condition(
    ::ZeroVelocityInitialCondition,
    q::Quadrature,
    problem::FluidFlowProblem,
    x::T,
    y::T,
) where {T <: Real}
    copy(q.weights)
end


text:
  module placer

  using Reexport

  include("../../ROOT/placer/engine/main.jl")

    using .engine

    @reexport using .engine

  export web_server

  import Random
using HTTP
import JSON

place
simulated_annealing_legalization

function web_server()
    @info "Listening on localhost:8082 .."
    # FIXME 8081 seems to be used by jupyterhub, I'm thus using 8082
    HTTP.serve("0.0.0.0", 8082) do request::HTTP.Request
        @show request
        @show request.method

        payload = HTTP.payload(request)
        # CAUTION the String constructor method will clear the payload!
        # String(payload)

        @info "parsing payload .."
        jstr = String(payload)

        # DEBUG write for future de use
        #open("spec.json", "w") do io
        #   write(io, jstr)
        #end

        jobj = JSON.parse(jstr)
        xs, ys, as, ws, hs, Es, mask, diearea, params = decode_place_spec(jobj)
        @info "running placement .."

        # set seed. This should make the placement deterministic given the same
        # hyper-parameters
        Random.seed!(1234)

        solxs, solys = place(xs, ys, ws, hs, Es, mask, diearea,
                             nsteps=params["place-nsteps"],
                             nbins=params["place-nbins"])
        solxs, solys, solas, conflicts = simulated_annealing_legalization(
            solxs, solys, as, ws, hs, mask, diearea,
            ncycles=params["sa-ncycles"],
            nsteps=params["sa-nsteps"],
            stepsize=params["sa-stepsize"],
            theta_stepsize=params["sa-theta-stepsize"])

        # FIXME run iterations

        # @info "visualizing .."
        # R = Region(xs, ys, ws, hs, 300)
        # TODO for each incoming request, plot the process and save as log
        # visualize(xs, ys, ws, hs, R)
        # visualize(solxs, solys, ws, hs, R)

        @info "sending results back .."
        # I'll only send back cells, or cell locations
        # res_payload = encode(jobj, solxs, solys)
        #
        # the new payload just encode the xs and ys
        #
        # transform the result to corner based, because racket pict system convention
        #
        # UPDATE I'm using center at every locations, to be consistent for fixed locations
        # solxs = solxs .- ws ./ 2
        # solys = solys .- hs ./ 2
        res_payload = Dict("xs"=>solxs, "ys"=>solys,
                           "as"=>solas,
                           # DEBUG
                           "ws"=>ws,
                           "hs"=>hs,
                           # should I add diearea here?
                           "diearea"=>diearea,
                           # for visualization and debug
                           "conflicts"=>conflicts) |> JSON.json

        # TODO I also want to send back visualizations UPDATE probably just send
        # back the coordinates and optionally meta data during the process. The
        # rendering can be done on the client side.

        # parse this directly as json, and save data to internal data structure
        # and start placement and routing.
        try
            # return HTTP.Response("Hello")
            return HTTP.Response(res_payload)
        catch e
            return HTTP.Response(404, "Error: $e")
        end
    end
end

decode_place_spec

  end

max_stars_repo_name: bhdl/bhdl

max_issues_repo_name: bhdl/bhdl

max_forks_repo_name: bhdl/bhdl


text:
"""
    Exo1Binion{T <: Real} = Parabolic{Binion{T}}

A 1-exo-binion is a parabolic Cayley-Dickson construct with binions.
"""
const Exo1Binion{T <: Real} = Parabolic{Binion{T}}

function Exo1Binion(z::Binion{T}) where T <: Real
    Exo1Binion{T}(z, zero(Binion{T}))
end

function Exo1Binion(a::T, b::T, c::T, d::T) where T <: Real
    Exo1Binion{T}(Binion{T}(a, b), Binion{T}(c, d))
end

function Exo1Binion(a::T, b::T, c::T) where T <: Real
    Exo1Binion{T}(Binion{T}(a, b), Binion{T}(c, zero(T)))
end

function Exo1Binion(a::T, b::T) where T <: Real
    Exo1Binion{T}(Binion{T}(a, b), zero(Binion{T}))
end

function Exo1Binion(a::T) where T <: Real
    Exo1Binion{T}(Binion{T}(a, zero(T)), zero(Binion{T}))
end

function Exo1Binion(a::Real, b::Real)
    Exo1Binion(promote(a, b)...)
end

function Exo1Binion(a::Real, b::Real, c::Real)
    Exo1Binion(promote(a, b, c)...)
end

function Exo1Binion(a::Real, b::Real, c::Real, d::Real)
    Exo1Binion(promote(a, b, c, d)...)
end

function Exo1Binion(z::Exo1Real{T}) where T <: Real
    Exo1Binion(z.l, zero(T), z.r, zero(T))
end

function selfstar(z::Exo1Binion)
    (z + star(z)) / 2
end

function anti_selfstar(z::Exo1Binion)
    (z - star(z)) / 2
end

"""
    unreal(z::Exo1Binion)

The unreal part of a 1-exo-binion is a 3-vector.
"""
function unreal(z::Exo1Binion)
    vcat(unreal(z.l), array(z.r))
end

function show(io::IO, z::Exo1Binion)
    print(io, "[1: ")
    print(io, z.l.l)
    print(io, ", i: ")
    print(io, z.l.r)
    print(io, ", a: ")
    print(io, z.r.l)
    print(io, ", ia: ")
    print(io, z.r.r)
    print(io, "]")
end

function random(::Type{Exo1Binion{T}}) where T <: Real
    Exo1Binion{T}(random(Binion{T}), random(Binion{T}))
end


text:
"""
    function mutateLHC!(rng,LHC,mut_inds)
Perform one random mutation to the LHC. Interchange two randomly selected elements
from a randomly selected column.
"""
function mutateLHC!(rng,LHC,mut_inds)

    n, d = size(LHC)         #Num points, num dimensions
    mut_range = 1:n          #Range of points per dim for mutation
    mut_dim = 1:d            #Range of dimensions for randomly choosen dimension

    mut_inds = sample!(rng, mut_range, mut_inds, replace = false) #Two unique & random indices
    ind1,ind2 = mut_inds

    rnd_col = rand(rng,mut_dim)   #Randomly choosen column (dimension)

    #Swap elements
    mut_tmp = LHC[ind1,rnd_col]
    LHC[ind1,rnd_col] = LHC[ind2,rnd_col]
    LHC[ind2,rnd_col] = mut_tmp

    return
end

"""
    function tournament!(rng,popfit_inds,tour_num,tour_inds,prob)
Choose `tour_num` random, unique, individuals and choose the best individual
with probability `prob`. Return selected individual index
"""
function tournament!(rng,popfit_inds,tour_num,tour_inds,prob)

    sample!(rng, popfit_inds, tour_inds, replace = false)::Array{Int64,1}

    sort!(tour_inds, rev=true)

    for i in 1:tour_num-1
        if rand(rng) <= prob
            return popfit_inds[tour_inds[i]]     #Winner!
        end
    end
    return popfit_inds[tour_inds[end]]           #Lucky chum!
end

"""
    function _fixedcross!(rng,offspr,parone,partwo)
Fixed point crossover of two parents to create one offspring.
"""
function _fixedcross!(rng,offspr,parone,partwo)

    offspr .= 0

    #generate a random location in the gene
    n = length(parone)
    loc = sample(rng,1:n-1)
    offspr[1:loc] = parone[1:loc]
    i = loc+1
    while i < n+1
        for j = 1:n
            x = findfirst(isequal(partwo[j]), offspr)
            if (x isa Nothing) && (offspr[i] == 0)
                offspr[i] = partwo[j]
                i += 1
            end
        end
    end

    return offspr

end

"""
    function fixedcross!(rng,offsprone,offsprtwo,parone,partwo)
Fixed point crossover of two parents to create two offspring.
"""
function fixedcross!(rng,offsprone,offsprtwo,parone,partwo)

    _fixedcross!(rng,offsprone,parone,partwo)
    _fixedcross!(rng,offsprtwo,partwo,parone)

    return offsprone, offsprtwo

end

"""
    function inversion!(rng,individual)
Reverse the values in a gene between two random cut-off points.
"""
function inversion!(rng,individual)

    #generate two, unique, random locations in the gene
    loc = sample(rng, 1:length(individual), 2, replace = false)

    #flip the values in the range in place
    reverse!(individual, minimum(loc),maximum(loc))

    return

end


text:
export NetCDFCube
import CFTime
mutable struct NetCDFCube{T,N,S} <: AbstractCubeData{T,N}
  file::String
  varname::String
  axes::Vector{CubeAxis}
  mv::T
  subset::S
  properties
end

function NetCDFCube(file,variable)
  NetCDF.open(file) do nc
    v = nc.vars[variable]
    #Find lon,lat,time dimensions if they exist
    cubeaxes = CubeAxis[]
    for dim in v.dim
    dimname=dim.name
    if startswith(uppercase(dimname),"LON")
      haskey(nc.vars,dimname) || error("Longitude variable does not exist")
      push!(cubeaxes,LonAxis(range(nc.vars[dimname][1], stop=nc.vars[dimname][end], length=dim.dimlen)))
    elseif startswith(uppercase(dimname),"LAT")
      haskey(nc.vars,dimname) || error("Latitude variable does not exist")
      push!(cubeaxes,LatAxis(range(nc.vars[dimname][1], stop=nc.vars[dimname][end], length=dim.dimlen)))
    elseif startswith(uppercase(dimname),"TIME")
      haskey(nc.vars,dimname) || error("Time variable does not exist")
      timvals = nc.vars[dimname][:]
      if haskey(nc.vars[dimname].atts,"units")
        cal = get(nc.vars[dimname].atts,"calendar","standard")
        push!(cubeaxes,TimeAxis(CFTime.timedecode(timvals,nc.vars[dimname].atts["units"],cal, prefer_datetime = true)))
      else
        push!(cubeaxes,RangeAxis(dimname,timvals))
      end
      haskey(nc.vars,dimname) || error("Longitude variable does not exist")
    else
      push!(cubeaxes,CategoricalAxis(dimname,haskey(nc.vars,dimname) ? nc.vars[dimname][:] : collect(1:dim.dimlen)))
    end
    end
    mv = get(v.atts,"missing_value",nothing)
    et = mv === nothing ? eltype(v) : Union{Missing,eltype(v)}
    NetCDFCube{et,length(cubeaxes),Nothing}(file,variable,cubeaxes,mv,nothing,Dict{Any,Any}())
  end
end
function subsetcube(z::NetCDFCube{T};kwargs...) where T
  subs = isa(z.subset,Nothing) ? collect(Any,map(Base.OneTo,size(z))) : collect(Any,z.subset)
  newaxes, substuple = _subsetcube(z,subs;kwargs...)
  NetCDFCube{T,length(newaxes),typeof(substuple)}(z.file,z.varname,newaxes,z.mv,substuple,z.properties)
end
Base.size(x::NetCDFCube)=ntuple(i->length(x.axes[i]),length(x.axes))
Base.size(x::NetCDFCube,i)=length(x.axes[i])
function iscompressed(x::NetCDFCube)
  NetCDF.open(x.file, x.varname) do v
    v.compress>0
  end
end
caxes(v::NetCDFCube)=deepcopy(v.axes)
getCubeDes(v::NetCDFCube)="NetCDF data cube"
function _read(x::NetCDFCube{T,N},thedata::AbstractArray,r::CartesianIndices{N}) where {T,N}
  allinds = NetCDF.open(x.file,x.varname) do v
    (map(i->Base.OneTo(i.dimlen),v.dim)...,)
  end |> CartesianIndices
  subinds = map(getindex,allinds.indices,getsubset(x))
  r2 = getsubinds(subinds,r.indices)
  sta = map(first,r2) |> collect
  cou = map(length,r2) |> collect
  d = ncread(x.file,x.varname,start = sta,count=cou)
  map!(i->isequal(i,x.mv) ? missing : i, thedata,d)
end


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

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local iv = try Base.loaded_modules[Base.PkgId(Base.UUID("6e696c72-6542-2067-7265-42206c756150"), "AbstractPlutoDingetjes")].Bonds.initial_value catch; b -> missing; end
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : iv(el)
        el
    end
end

# ╔═╡ f4c883b8-e2e9-11ec-28de-addab043979e
begin
	import Pkg
    Pkg.activate(Base.current_project())
    Pkg.instantiate()

	using PlutoUI, LabelledArrays, EzXML
    using Plots, MetaGraphsNext, Graphs, GraphPlot, Compose
    using PNML: PNML, pid
end

# ╔═╡ f87a98af-6af6-4a0a-819b-3e472eafe54a
# ╠═╡ show_logs = false
let
	versioninfo()
	Pkg.status()
end

# ╔═╡ 41566501-e86b-41af-bd01-2d2f999cc54f
md"""
birth rate $(@bind BR_slider NumberField(0.0:0.01:1.0; default=0.3))

death rate $(@bind DR_slider NumberField(0.0:0.01:1.0; default=0.7))

predatation rate $(@bind PR_slider NumberField(0.0:0.001:0.2; default=0.015))
"""

# ╔═╡ 812bda06-fd40-4b65-b5fa-0aae0c2c8832
# Experimental versions on the XML.
xml2 = """<?xml version="1.0"?>
<pnml xmlns="http://www.pnml.org/version-2009/grammar/pnml">
<net id="net0" type="continuous">
<page id="page0">
  <place id="rabbits"> <initialMarking>100.0</initialMarking> </place>
  <place id="wolves">  <initialMarking> <text>10.0</text> </initialMarking> </place>
  <transition id ="birth">     <rate> $BR_slider </rate> </transition>
  <transition id ="death">     <rate> $DR_slider </rate> </transition>
  <transition id ="predation"> <rate> $PR_slider </rate> </transition>
  <arc id="a1" source="rabbits"   target="birth">     <inscription><text>1</text> </inscription> </arc>
  <arc id="a2" source="birth"     target="rabbits">   <inscription><text>2</text> </inscription> </arc>
  <arc id="a3" source="wolves"    target="predation"> <inscription><text>1</text> </inscription> </arc>
  <arc id="a4" source="rabbits"   target="predation"> <inscription><text>1</text> </inscription> </arc>
  <arc id="a5" source="predation" target="wolves">    <inscription><text>2</text> </inscription> </arc>
  <arc id="a6" source="wolves"    target="death">     <inscription><text>1</text> </inscription> </arc>
</page>
</net>
</pnml>
"""

# ╔═╡ 602978fa-4e05-4546-b205-d027880f0ccd
net = PNML.SimpleNet(xml2)

# ╔═╡ 221681e3-656d-4fa1-8425-cece133df01d
S = PNML.place_ids(net)

# ╔═╡ ccb4e098-51b1-46dd-b563-1074a7ea9d82
T = PNML.transition_ids(net)

# ╔═╡ 9f5d18d5-f8b7-44d2-8ddf-8b38be57a0a4
A = PNML.arc_ids(net)

# ╔═╡ f282f10d-8e6a-462e-be8a-4c072df82d0a
# LabelledArrays when empty (dimension 0) use Union{} as the element type.
# Which errors under Pluto and suggests fix of defining this method.
Base.show(io::IO, ::MIME{Symbol("image/svg+xml")}, ::AbstractVector{Union{}}) = print(io, "∅")

# ╔═╡ 0e9edbf3-df2c-474b-b747-6789dac7a398
Δ = PNML.transition_function(net)

# ╔═╡ 7d77e7ca-ad32-435a-895e-697dc91c340d
petri = MetaGraph( DiGraph();
		VertexData = PNML.PnmlNode, #String, # marking, condition
		EdgeData = PNML.Arc, #Symbol,  # inscription
		graph_data = "graph_of_pnml")

# ╔═╡ c163301f-964e-4b79-b5f2-39c7bb17d085
for p in S
	petri[p] = PNML.place(net, p)
end

# ╔═╡ 7fc99e91-963a-4ffc-bea3-c54adc652c78
for t in T
	petri[t] = PNML.transition(net, t)
end

# ╔═╡ 596c2657-01ce-4f0a-99d6-10aeae963271
for a in A
	arc = PNML.arc(net, a)
	petri[PNML.source(arc), PNML.target(arc)] = arc
end

# ╔═╡ a127b05a-fcea-4712-be3c-03f96739de82
petri

# ╔═╡ 9b6e1948-e841-42b3-b315-e08b136bf047
PNML.inscription(petri[:birth, :rabbits])

# ╔═╡ c6e10d0d-019d-4fac-98a9-8774dce3af18
petri[:wolves]

# ╔═╡ c4802576-8425-4e66-aa3d-3fdb405a315e
petri[:rabbits, :birth]

# ╔═╡ 1ae71749-88eb-4b76-9ba0-901892bce079
collect(label_for.(Ref(petri),vertices(petri)))

# ╔═╡ f16359db-8e21-42ae-bb4d-eb8a6a75b992
collect(edges(petri))

# ╔═╡ 2700ad27-4a1e-4410-b9c3-e288059473f9
# ╠═╡ show_logs = false
map(edges(petri)) do e
	@show src(e), dst(e)
	pid(petri[label_for(petri,src(e)), label_for(petri,dst(e))])
end

# ╔═╡ 1cfda3d4-e653-4629-b377-cad4ea8ce85a
[pid(petri[label_for(petri,src(e)), label_for(petri,dst(e))]) for e in edges(petri)]

# ╔═╡ 8ed47098-345d-46d6-aaec-1799ce2f3264
map(vertices(petri)) do v
	pid(petri[label_for(petri,v)])
end

# ╔═╡ ed61c205-1b45-45f2-b6fa-76095e7c898e
gplot(petri;
	nodelabel=collect(label_for.(Ref(petri),vertices(petri))),
	edgelabel=[pid(petri[label_for(petri,src(e)), label_for(petri,dst(e))]) for e in edges(petri)]
	)

# ╔═╡ 13b8de0b-84ee-4ba8-abba-0fe353df206c
md"""
#### Appendix

Utilities, references, et al.
"""

# ╔═╡ 5c9c1c4f-c635-4275-a0b3-7b39ca1b8ddf

# ╔═╡ Cell order:
# ╠═f4c883b8-e2e9-11ec-28de-addab043979e
# ╠═f87a98af-6af6-4a0a-819b-3e472eafe54a
# ╠═812bda06-fd40-4b65-b5fa-0aae0c2c8832
# ╠═41566501-e86b-41af-bd01-2d2f999cc54f
# ╠═602978fa-4e05-4546-b205-d027880f0ccd
# ╠═221681e3-656d-4fa1-8425-cece133df01d
# ╠═ccb4e098-51b1-46dd-b563-1074a7ea9d82
# ╠═9f5d18d5-f8b7-44d2-8ddf-8b38be57a0a4
# ╟─f282f10d-8e6a-462e-be8a-4c072df82d0a
# ╠═0e9edbf3-df2c-474b-b747-6789dac7a398
# ╠═7d77e7ca-ad32-435a-895e-697dc91c340d
# ╠═c163301f-964e-4b79-b5f2-39c7bb17d085
# ╠═7fc99e91-963a-4ffc-bea3-c54adc652c78
# ╠═596c2657-01ce-4f0a-99d6-10aeae963271
# ╠═a127b05a-fcea-4712-be3c-03f96739de82
# ╠═9b6e1948-e841-42b3-b315-e08b136bf047
# ╠═c6e10d0d-019d-4fac-98a9-8774dce3af18
# ╠═c4802576-8425-4e66-aa3d-3fdb405a315e
# ╠═1ae71749-88eb-4b76-9ba0-901892bce079
# ╠═8ed47098-345d-46d6-aaec-1799ce2f3264
# ╠═f16359db-8e21-42ae-bb4d-eb8a6a75b992
# ╠═2700ad27-4a1e-4410-b9c3-e288059473f9
# ╠═1cfda3d4-e653-4629-b377-cad4ea8ce85a
# ╠═ed61c205-1b45-45f2-b6fa-76095e7c898e
# ╟─13b8de0b-84ee-4ba8-abba-0fe353df206c
# ╠═5c9c1c4f-c635-4275-a0b3-7b39ca1b8ddf