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

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

"""

Deallocates a specific virtual machine in a VM scale set. Shuts down the virtual machine and releases the compute resources it uses. You are not billed for the compute resources of this virtual machine once it is deallocated.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsDeallocate(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/deallocate", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsDeallocate(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsDeallocate(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsDeallocate(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsDeallocate(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Deletes a virtual machine from a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsDelete(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "DELETE", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsDelete(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsDelete(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsDelete(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsDelete(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets a virtual machine from a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Param: expand::String
Return: VirtualMachineScaleSetVM
"""
function _swaggerinternal_virtualMachineScaleSetVMsGet(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", VirtualMachineScaleSetVM, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "\$expand", expand)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsGet(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsGet(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; expand=expand, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsGet(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; expand=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsGet(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; expand=expand, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets the status of a virtual machine from a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: VirtualMachineScaleSetVMInstanceView
"""
function _swaggerinternal_virtualMachineScaleSetVMsGetInstanceView(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", VirtualMachineScaleSetVMInstanceView, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/instanceView", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsGetInstanceView(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsGetInstanceView(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsGetInstanceView(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsGetInstanceView(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Gets a list of all virtual machines in a VM scale sets.
Param: resourceGroupName::String (required)
Param: virtualMachineScaleSetName::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Param: filter::String
Param: select::String
Param: expand::String
Return: VirtualMachineScaleSetVMListResult
"""
function _swaggerinternal_virtualMachineScaleSetVMsList(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, virtualMachineScaleSetName::String, api_version::String, subscriptionId::String; filter=nothing, select=nothing, expand=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "GET", VirtualMachineScaleSetVMListResult, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{virtualMachineScaleSetName}/virtualMachines", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "virtualMachineScaleSetName", virtualMachineScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "\$filter", filter)  # type String
    Swagger.set_param(_ctx.query, "\$select", select)  # type String
    Swagger.set_param(_ctx.query, "\$expand", expand)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsList(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, virtualMachineScaleSetName::String, api_version::String, subscriptionId::String; filter=nothing, select=nothing, expand=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsList(_api, resourceGroupName, virtualMachineScaleSetName, api_version, subscriptionId; filter=filter, select=select, expand=expand, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsList(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, virtualMachineScaleSetName::String, api_version::String, subscriptionId::String; filter=nothing, select=nothing, expand=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsList(_api, resourceGroupName, virtualMachineScaleSetName, api_version, subscriptionId; filter=filter, select=select, expand=expand, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Performs maintenance on a virtual machine in a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsPerformMaintenance(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/performMaintenance", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsPerformMaintenance(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsPerformMaintenance(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsPerformMaintenance(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsPerformMaintenance(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Power off (stop) a virtual machine in a VM scale set. Note that resources are still attached and you are getting charged for the resources. Instead, use deallocate to release resources and avoid charges.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Param: skipShutdown::Bool
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsPowerOff(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; skipShutdown=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/poweroff", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "skipShutdown", skipShutdown)  # type Bool
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsPowerOff(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; skipShutdown=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsPowerOff(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; skipShutdown=skipShutdown, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsPowerOff(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; skipShutdown=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsPowerOff(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; skipShutdown=skipShutdown, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Shuts down the virtual machine in the virtual machine scale set, moves it to a new node, and powers it back on.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsRedeploy(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/redeploy", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsRedeploy(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsRedeploy(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsRedeploy(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsRedeploy(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Reimages (upgrade the operating system) a specific virtual machine in a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Param: vmScaleSetVMReimageInput::VirtualMachineScaleSetVMReimageParameters
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsReimage(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; vmScaleSetVMReimageInput=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/reimage", ["azure_auth"], vmScaleSetVMReimageInput)
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsReimage(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; vmScaleSetVMReimageInput=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsReimage(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; vmScaleSetVMReimageInput=vmScaleSetVMReimageInput, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsReimage(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; vmScaleSetVMReimageInput=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsReimage(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; vmScaleSetVMReimageInput=vmScaleSetVMReimageInput, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Allows you to re-image all the disks ( including data disks ) in the a VM scale set instance. This operation is only supported for managed disks.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsReimageAll(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/reimageall", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsReimageAll(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsReimageAll(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsReimageAll(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsReimageAll(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Restarts a virtual machine in a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsRestart(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/restart", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsRestart(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsRestart(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsRestart(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsRestart(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

The operation to retrieve SAS URIs of boot diagnostic logs for a virtual machine in a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Param: sasUriExpirationTimeInMinutes::Int32
Return: RetrieveBootDiagnosticsDataResult
"""
function _swaggerinternal_virtualMachineScaleSetVMsRetrieveBootDiagnosticsData(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; sasUriExpirationTimeInMinutes=nothing, _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", RetrieveBootDiagnosticsDataResult, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/retrieveBootDiagnosticsData", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "sasUriExpirationTimeInMinutes", sasUriExpirationTimeInMinutes)  # type Int32
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsRetrieveBootDiagnosticsData(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; sasUriExpirationTimeInMinutes=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsRetrieveBootDiagnosticsData(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; sasUriExpirationTimeInMinutes=sasUriExpirationTimeInMinutes, _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsRetrieveBootDiagnosticsData(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; sasUriExpirationTimeInMinutes=nothing, _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsRetrieveBootDiagnosticsData(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; sasUriExpirationTimeInMinutes=sasUriExpirationTimeInMinutes, _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

The operation to simulate the eviction of spot virtual machine in a VM scale set. The eviction will occur within 30 minutes of calling the API
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsSimulateEviction(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualMachines/{instanceId}/simulateEviction", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsSimulateEviction(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsSimulateEviction(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsSimulateEviction(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsSimulateEviction(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Starts a virtual machine in a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: Nothing
"""
function _swaggerinternal_virtualMachineScaleSetVMsStart(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "POST", Nothing, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}/start", ["azure_auth"])
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsStart(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsStart(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsStart(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsStart(_api, resourceGroupName, vmScaleSetName, instanceId, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

"""

Updates a virtual machine of a VM scale set.
Param: resourceGroupName::String (required)
Param: vmScaleSetName::String (required)
Param: instanceId::String (required)
Param: parameters::VirtualMachineScaleSetVM (required)
Param: api_version::String (required)
Param: subscriptionId::String (required)
Return: VirtualMachineScaleSetVM
"""
function _swaggerinternal_virtualMachineScaleSetVMsUpdate(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = Swagger.Ctx(_api.client, "PUT", VirtualMachineScaleSetVM, "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachineScaleSets/{vmScaleSetName}/virtualmachines/{instanceId}", ["azure_auth"], parameters)
    Swagger.set_param(_ctx.path, "resourceGroupName", resourceGroupName)  # type String
    Swagger.set_param(_ctx.path, "vmScaleSetName", vmScaleSetName)  # type String
    Swagger.set_param(_ctx.path, "instanceId", instanceId)  # type String
    Swagger.set_param(_ctx.path, "subscriptionId", subscriptionId)  # type String
    Swagger.set_param(_ctx.query, "api-version", api_version)  # type String
    Swagger.set_header_accept(_ctx, ["application/json"])
    Swagger.set_header_content_type(_ctx, (_mediaType === nothing) ? ["application/json"] : [_mediaType])
    return _ctx
end

function virtualMachineScaleSetVMsUpdate(_api::VirtualMachineScaleSetVMsApi, resourceGroupName::String, vmScaleSetName::String, instanceId::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsUpdate(_api, resourceGroupName, vmScaleSetName, instanceId, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx)
end

function virtualMachineScaleSetVMsUpdate(_api::VirtualMachineScaleSetVMsApi, response_stream::Channel, resourceGroupName::String, vmScaleSetName::String, instanceId::String, parameters, api_version::String, subscriptionId::String; _mediaType=nothing)
    _ctx = _swaggerinternal_virtualMachineScaleSetVMsUpdate(_api, resourceGroupName, vmScaleSetName, instanceId, parameters, api_version, subscriptionId; _mediaType=_mediaType)
    Swagger.exec(_ctx, response_stream)
end

export virtualMachineScaleSetVMsDeallocate, virtualMachineScaleSetVMsDelete, virtualMachineScaleSetVMsGet, virtualMachineScaleSetVMsGetInstanceView, virtualMachineScaleSetVMsList, virtualMachineScaleSetVMsPerformMaintenance, virtualMachineScaleSetVMsPowerOff, virtualMachineScaleSetVMsRedeploy, virtualMachineScaleSetVMsReimage, virtualMachineScaleSetVMsReimageAll, virtualMachineScaleSetVMsRestart, virtualMachineScaleSetVMsRetrieveBootDiagnosticsData, virtualMachineScaleSetVMsSimulateEviction, virtualMachineScaleSetVMsStart, virtualMachineScaleSetVMsUpdate


text: @test 1 == 1

ext: jl


text:
using Random

export AbstractAgent, start!, step!, get_action

abstract type AbstractAgent end

"""
    start!(agent::AbstractAgent, env_s_tp1, args...)

Function for starting the agent for a new episode.

returns an action to get passed to the environment
"""
function start!(agent::AbstractAgent, env_s_tp1, args...)
    @error "Implement start! for $(typeof(agent))"
end

"""
    step!(agent::AbstractAgent, env_s_tp1, r, terminal, args...)

Function to take a step with an agent.

Returns an action to get passed to the environment.
"""
function step!(agent::AbstractAgent, env_s_tp1, r, terminal, args...)
    @error "Implement step! for $(typeof(agent))"
end


text:
module rings
using LinearAlgebra, DSP
include("cheb.jl")
using .cheb
export ring

"""
UNITS: cgs

"""

ASSERT = true # for debugging purposes: include "@assert" statements

# Consts
G  = 6.67430e-8 # Gravitational constant, cgs
M♄ = 5.6834e29  # mass of Saturn, in grams
A₁ = 6.7187     # Goldreich-Tremaine constant
Mm = 1.0e8      # Megameter. Typical orbit is 100Mm.

# Some fiducial satellites, for reference:
Pan  = (4.95e19, 1.33584e10) # (mass, orbital radius) of Pan (Encke gap)
Daph = (8.40e16, 1.36504e10) # (mass, orbital radius) of Daphnis (Keeler gap)

"""
"aring" is an abstract, idealized 1D (in r, i.e. in x) ring, with periodic b.c.
in the approximation that Δr ≪ r, and with a single mass forcing a gap.

- velocity is normalized to the diffusive wave speed √(κ₀/s₀)
- position is normalized to the critical lengthscale, Lcrit
- density Σ is normalized to the fiducial density Σ₀:  σ ≡ Σ/Σ₀
- the periodic bc includes prescription that σ = 1 at the midpoint
"""

struct chebars
    yf::Array{Float64}
    y::Array{Float64}
    D1::Array{Float64,2}
    De::Array{Float64,2}
    Do::Array{Float64,2}
end

mutable struct aring # an abstract, idealized 1D (in r) ring, with periodic BC's and a single forcing moon
    X₀::Float64  # THE key nondimensional parameter.
    ℓ₀::Float64  # The other non-dimensional parameter: sets the size of the domain (in units of Lcrit).
    #
    N::Integer   # number of nodes for a full ring
    nn::Integer  # number of nodes for a half-ring (N÷2 + N%2)
    #
    #ξ::Array{Float64}  # position x normalized to Lcrit
    #Ξ::Array{Float64}  # position x normalized to Lvisc
    #
    β::Float64 # exponent for σ-dependence of viscosity (and diffusivity)
    γ::Float64 # exponent for σ-dependence of relaxation rate 1/s
    #
    chArs::chebars # Tuple of chebdif arrays
    #
    w::Array{Float64}
    σ::Array{Float64}
    Ar::Any
    a::Any
    Br::Any
    b::Any
end

"""
Functions for getting "A" matrix and "a" vector.
"""
function getA(De,σ,w,β,γ)#;hrel=0.0)
    A  = diagm((1+β)*σ.^(β+γ) .- w.^2) * De
    Ar = A[:,2:end-1]
    a  = A[:,end]
    return (Ar,a)
end
function getA!(r::aring)
    (r.Ar,r.a) = getA( r.chArs.De , r.σ , r.w , r.β , r.γ )
end

"""
Functions for getting "B" matrix and "b" vector.
"""
function getB(Do,σ,w,γ,ℓ₀,τ)
    # Get B1.
    B1 = diagm(w.*σ.^γ) ./ (ℓ₀-1) ./ τ
    B1r = B1[:,2:end-1]
    b1  = B1[:,end]
    # And B2.
    B2 = 2 * diagm(w) * diagm(Do*w)
    B2r = B2[:,2:end-1]
    b2  = B2[:,end]
    # Combine
    Br = B1r + B2r
    b  = b1  + b2
    # And return:
    return (Br,b)
end
function getB!(ar::aring)
    τ = ar.X₀^(-1/8)
    (ar.Br, ar.b) = getB( ar.chArs.Do , ar.σ , ar.w , ar.γ , ar.ℓ₀, τ)
end

"""
Functions for setting the normalized velocity "w".
    hrel is the Hill radius relative to Lcrit.
"""
function getw(y,ℓ₀ ; hrel=0.0) # -1 ≤ y ≤ 1
    if ASSERT
        @assert -1 ≤ y ≤ 1
        @assert hrel ≥ 0.0
    end
    ξL = y * (ℓ₀-1) + ℓ₀ #  1 ≤ ξL = position relative to mass on left  (dim'less)
    ξR = y * (ℓ₀-1) - ℓ₀ # -1 ≥ ξR = position relative to mass on right (dim'less)
    # In principle, we should consider a mass at ..., -4L₀, -2L₀, 0, 2L₀, 4L₀, ...,
    #    but honestly, that's overkill in all situations of interest I can think of here.
    # We could also test here whether |ξL| > 2.5*hrel and |ξR| > 2.5*hrel, but we don't, b/c
    #   we might want to violate that in the early stages of an iterative solution.
    # That condition should be tested elswhere, however.
    if hrel ≈ 0.0
        return ξL^-4 - ξR^-4
    else
        aa = 0.711557; bb = -7.58607 # Constants given by Grätz, Seiß & Spahn (2018), p. 3.
        function g(hox)
            min(1/2.5,abs(hox))
        end
        function f(hox)
            (1+ aa*g(hox) + bb*g(hox)^2)^(-1)
        end
        function ww(ξ)
            sign(ξ)/ξ^4 * f(hrel/ξ)
        end
        wL = ww(ξL)
        wR = ww(ξR)
        return wL + wR
    end
end
function getw!(ar::aring ; hrel::Real=0.0)
    ar.w = getw.(ar.chArs.y,ar.ℓ₀;hrel)
    #ar.w = w[1:ar.nn]
end

function iterate!(ar::aring; hrel=0.0)
    getw!(ar; hrel)
    getA!(ar)
    getB!(ar)
    # Solve:
    nn= ar.nn
    print(size(ar.Ar))
    @assert size(ar.Ar) == (nn,nn-2)
    @assert size(ar.a) == (nn,)
    @assert size(ar.Br) == (nn,nn-2)
    @assert size(ar.b) == (nn,)
    σ = (ar.Ar - ar.Br) \ (ar.b - ar.a)
    ar.σ = [0, σ..., 1]
    #ar.σ = σ
    #
    return 0
end

"""
Normal function to initialize an instance of "aring".
"""
function aring(X₀,ℓ₀,N,β,γ; hrel=0.0) # h is the Hill radius in units of Lcrit
    if ASSERT
        @assert X₀ > 2^24           # 2^24 is critical value for X; below this, the method does not apply
        @assert ℓ₀ > 3              # L0/Lcrit needs to be greater than a few; this is a bit of a fuzzy boundary, but certainly > 3.
        @assert ℓ₀ * X₀^(1/24) > 3  # Same for L0/Lvisc; this makes the above line redundant, I know - kept as a mnemonic
    end
    #
    # Find nn, which is half of N, since we treat only half the domain.
    # (Why not just specify nn to start? So we can test/try both odd and even N for the full domain.)
    nn = N÷2 + N%2 # nn: "non-negative" (positions)
    #
    # Get collocation points and differentiation matrices
    # Note that y, D1, De, and Do operate on the domain -1 ≤ y ≤ 1. Need to normalize to -ℓ₀ ≤ ξ ≤ ℓ₀.
    (yf,DM,DeM,DoM) = chebdif(N,1)
    D1 = DM[:,:,1]   # full derivative matrix (N x N)
    y = yf[1:nn]
    De = DeM[:,:,1]   # derivative of even functions (nn x nn)
    Do = DoM[:,:,1]   # derivative of odd functions (nn x nn)
    chArs = chebars(yf,y,D1,De,Do) # for
    #
    # Get (dim'less) velocity:
    w = getw.(y,ℓ₀; hrel)
    #
    # Get "A" and "a"
    σ = ones(nn); # just to start
    (Ar,a) = getA(De,σ,w,β,γ)
    #
    # Get "B" and "b"
    τ = X₀^(-1/8)
    (Br,b) = getB(Do,σ,w,β,τ,ℓ₀)
    #
    ar = aring(X₀, ℓ₀, N, nn, β, γ, chArs, w, σ, Ar, a, Br, b)
    iterate!(ar)
    return ar
end

struct ring
    ar::aring
    moon::Tuple # mass, a0
    disk::Tuple # nu, srel
    X₀::Float64 # fundamental parameter
    β::Float64
    γ::Float64
    Lset::Tuple # lengthscales
    gap::Tuple # width, Δwidth
    h::Float64  # Hill radius
end
function ring(m,β,γ;N=1000,a0=1.0e10,ν=1.0,srel=30,ξ₀=10)#,h=0.0)
    function Ω(a₀)
        return √(G*M♄/a₀^3)
    end
    a₀=a0
    Ω = Ω(a₀)
    α = A₁^2 / 18π * Ω * (m/M♄)^2 * a₀^5
    s₀ = srel / Ω
    κ₀ = 3ν
    X₀ = α^2/κ₀^5/s₀^3
    h = a0 * (m/3/M♄)^(1/3) # Hill radius (in physical units, i.e. cm).

    Lvisc = (α/κ₀)^(1/3)
    w₀ = √(κ₀/s₀)
    Lcrit = (α/w₀)^(1/4)
    Lαs = (α*s₀)^0.2          # another lengthscale constructed from α, ν, s
    Lκs = √(κ₀*s₀)
    Lset = (Lvisc,Lcrit,Lαs,Lκs)

    ar = aring(X₀,ξ₀,N,β,γ; hrel=h/Lcrit)

    for i in 1:5
        iterate!(r)
    end
    # Smooth:
    r.σ = conv(r.σ,[1,4,6,4,1]./16)[3:end-2]
    #

    i10 = findfirst(x->x>0.1,r.σ)
    ξ10 = r.ξ[i10]

    i50 = findfirst(x->x>0.5,r.σ)
    ξ50 = r.ξ[i50]

    i90 = findfirst(x->x>0.9,r.σ)
    ξ90 = r.ξ[i90]

    width = 2*(ξ50 * Lcrit)
    Δwidth = 2*(ξ90-ξ10)*Lcrit
    #width=(0.0,0.0)
    #Δwidth=(0.0,0.0)
    h*=0
    return rring(r,(m,a0),(ν,srel),X₀,β,γ,Lset,(width,Δwidth,2*ξ90*Lcrit,2*ξ10*Lcrit),h)
    # Get 10%, 50%, 90% points
end

end#module

max_stars_repo_name: diakosmos/razor

max_issues_repo_name: diakosmos/razor

max_forks_repo_name: diakosmos/razor


text:
using DataAugmentation
using Images
using StaticArrays
using Test
using TestSetExtensions
using CoordinateTransformations

using DataAugmentation: Item, Transform, getrandstate, itemdata, setdata, ComposedProjectiveTransform,
    projectionbounds, getprojection, offsetcropbounds,
    CroppedProjectiveTransform, getbounds, project, project!, makebuffer, imagetotensor, imagetotensor!,
    normalize, normalize!, tensortoimage, denormalize, denormalize!,
    NormalizeRow, FillMissing, Categorify, TabularItem
using DataAugmentation: testitem, testapply, testapply!, testprojective
import DataAugmentation: apply, compose


text:
module Readers

using Avro.DataFile
using Avro.DataFile.Codecs
using Avro.Generic
using Avro.Io
using Avro.Schemas

export wrap

struct Reader
    input_decoder::BinaryDecoder
    schema::Schemas.Schema
    codec::Codec
    sync_marker::Vector{UInt8}
end

function wrap(input::IO)
    input_decoder = BinaryDecoder(input)

    header = _read_header(input_decoder)
    magic = getindex(header, 1)
    meta = getindex(header, 2)
    sync_marker = getindex(header, 3).bytes

    # The magic header is invalid
    if magic.bytes != OBJECT_CONTAINER_FILE_MAGIC
        throw("Not an Avro data file.")
    end

    # Parse the schema from the metadata
    schema = Schemas.parse(meta[META_SCHEMA_KEY])
    codec = Codecs.create(get(meta, META_CODEC_KEY, "null"))

    Reader(input_decoder, schema, codec, sync_marker)
end

function Base.close(file_reader::Reader)
    close(file_reader.input_decoder.stream)
end

function start(file_reader::Reader)
    _read_block_header(file_reader)
end

function next(file_reader::Reader, state)
    buffer_decoder, block_count = state
    if block_count == 0
        buffer_decoder, block_count = _read_block_header(file_reader)
    end
    item = read(buffer_decoder, file_reader.schema)
    item, (buffer_decoder, block_count - 1)
end

function done(file_reader::Reader, state)
    buffer_decoder, block_count = state
    if block_count == 0
        sync = read(file_reader.input_decoder, SYNC_SCHEMA)
        @assert file_reader.sync_marker == sync.bytes
    end
    eof(file_reader.input_decoder.stream)
end

function Base.iterate(file_reader::Reader, state)
    done(file_reader, state) ? nothing : next(file_reader, state)
end
Base.iterate(file_reader::Reader) = iterate(file_reader, start(file_reader))

Base.IteratorSize(::Type{Reader}) = Base.SizeUnknown()

Base.IteratorEltype(::Type{Reader}) = Base.HasEltype()

Base.eltype(::Type{Reader}) = GenericRecord

"""
Read the header directly the input decoder.
"""
function _read_header(input_decoder::BinaryDecoder)
    read(input_decoder, METADATA_SCHEMA)
end

function _read_block_header(file_reader::Reader)
    input_decoder = file_reader.input_decoder
    block_count = decode_long(input_decoder)
    num_bytes = decode_long(input_decoder)
    block_data = decode_fixed(input_decoder, num_bytes)
    block_data = Codecs.decompress(file_reader.codec, block_data)

    buffer_decoder = BinaryDecoder(IOBuffer(block_data))
    buffer_decoder, block_count
end

end


text:
using Test, Pkg
using MPI

@testset "mpiexecjl" begin
    mktempdir() do dir
        # Install MPI locally, so that we can test the `--project` flag to
        # `mpiexecjl`
        Pkg.activate(dir)
        Pkg.develop(PackageSpec(path=joinpath(@__DIR__, "..")))
        # Test installation
        @test_logs (:info, r"Installing") (:info, r"Done") MPI.install_mpiexecjl(; destdir = dir)
        # Test a run of mpiexec
        mpiexecjl = joinpath(dir, "mpiexecjl")
        julia = joinpath(Sys.BINDIR, Base.julia_exename())
        example = joinpath(@__DIR__, "..", "docs", "examples", "01-hello.jl")
        env = ["JULIA_BINDIR" => Sys.BINDIR]
        p = withenv(env...) do
            run(`$(mpiexecjl) --project=$(dir) $(julia) --startup-file=no -q $(example)`)
        end
        @test success(p)
        # Test help messages
        for help_flag in ("-h", "--help")
            help_message = withenv(env...) do
                read(`$(mpiexecjl) --project=$(dir) --help`, String)
            end
            @test occursin(r"Usage:.*MPIEXEC_ARGUMENTS", help_message)
        end
        # Without arguments, or only with the `--project` option, the wrapper will fail
        @test !withenv(() -> success(`$(mpiexecjl) --project=$(dir)`), env...)
        @test !withenv(() -> success(`$(mpiexecjl)`), env...)
    end
end


text:
@testset "Callback" begin
    ## Throttle
    game = MatrixGame()
    sol = DeepCFRSolver(game)
    io = IOBuffer()
    f = () -> println(io, length(sol.Mπ))
    save_freq = 10
    train_iter = 101
    cb = DeepCFR.Throttle(f,save_freq)
    train!(sol, train_iter, cb = cb)
    str = String(take!(io))
    @test length(split(str, "\n")) == div(train_iter, save_freq) + 2

    ## Model Saver
    sol = DeepCFRSolver(game)
    path = tempname(tempdir(); cleanup=true)
    cb = DeepCFR.ModelSaver(sol, save_freq, path=path)
    train!(sol, train_iter; cb = cb)

    file_list = readdir(path)
    @test length(file_list) == div(train_iter, save_freq) + 1
    model_path = joinpath(path,last(file_list))
    m = JLD2.load(model_path)["model"]
    @test typeof(m) == typeof(sol)

    ## Exploitability
    sol = DeepCFRSolver(game)
    cb = DeepCFR.ExploitabilityCallback(sol, 10)
    train!(sol, train_iter; cb = cb)
    @test length(cb.hist.y) == length(cb.hist.y) == 11
    @test first(cb.hist.y) > last(cb.hist.y) > 0.0

    ## Fitting
    sol = DeepCFRSolver(game)
    cb = DeepCFR.FittingCallback(sol)
    train!(sol, train_iter; cb=cb)
    @test length(cb.hist[1]) == length(cb.hist[2]) == train_iter
end


text:
#=
This file is auto-generated. Do not edit.
=#
"""
    mutable struct LCFilter <: Filter
        lf::Float64
        rf::Float64
        cf::Float64
        ext::Dict{String, Any}
        states::Vector{Symbol}
        n_states::Int64
        internal::InfrastructureSystemsInternal
    end

Parameters of a LCL filter outside the converter

# Arguments
- `lf::Float64`: filter inductance, validation range: (0, nothing)
- `rf::Float64`: filter resistance, validation range: (0, nothing)
- `cf::Float64`: filter capacitance, validation range: (0, nothing)
- `ext::Dict{String, Any}`
- `states::Vector{Symbol}`
- `n_states::Int64`
- `internal::InfrastructureSystemsInternal`: power system internal reference, do not modify
"""
mutable struct LCFilter <: Filter
    "filter inductance"
    lf::Float64
    "filter resistance"
    rf::Float64
    "filter capacitance"
    cf::Float64
    ext::Dict{String, Any}
    states::Vector{Symbol}
    n_states::Int64
    "power system internal reference, do not modify"
    internal::InfrastructureSystemsInternal
end

function LCFilter(lf, rf, cf, ext=Dict{String, Any}(), )
    LCFilter(lf, rf, cf, ext, [:id_o, :iq_o], 4, InfrastructureSystemsInternal(), )
end

function LCFilter(; lf, rf, cf, ext=Dict{String, Any}(), )
    LCFilter(lf, rf, cf, ext, )
end

# Constructor for demo purposes; non-functional.
function LCFilter(::Nothing)
    LCFilter(;
        lf=0,
        rf=0,
        cf=0,
        ext=Dict{String, Any}(),
    )
end

"""Get LCFilter lf."""
get_lf(value::LCFilter) = value.lf
"""Get LCFilter rf."""
get_rf(value::LCFilter) = value.rf
"""Get LCFilter cf."""
get_cf(value::LCFilter) = value.cf
"""Get LCFilter ext."""
get_ext(value::LCFilter) = value.ext
"""Get LCFilter states."""
get_states(value::LCFilter) = value.states
"""Get LCFilter n_states."""
get_n_states(value::LCFilter) = value.n_states
"""Get LCFilter internal."""
get_internal(value::LCFilter) = value.internal


text:
"""
# Optim.jl
Welcome to Optim.jl!

Optim.jl is a package used to solve continuous optimization problems. It is
written in Julia for Julians to help take advantage of arbitrary number types,
fast computation, and excellent automatic differentiation tools.

## REPL help
`?` followed by an algorithm name (`?BFGS`), constructors (`?Optim.Options`)
prints help to the terminal.

## Documentation
Besides the help provided at the REPL, it is possible to find help and general
documentation online at http://julianlsolvers.github.io/Optim.jl/stable/ .
"""
module Optim
using Compat
using NLSolversBase          # for shared infrastructure in JuliaNLSolvers

using PositiveFactorizations # for globalization strategy in Newton
import PositiveFactorizations: cholesky!, cholesky

using LineSearches           # for globalization strategy in Quasi-Newton algs

import NaNMath               # for functions that ignore NaNs (no poisoning)

import Parameters: @with_kw, # for types where constructors are simply defined
                   @unpack   # by their default values, and simple unpacking
                             # of fields

using Printf                 # For printing, maybe look into other options

using FillArrays             # For handling scalar bounds in Fminbox

#using Compat                 # for compatibility across multiple julia versions

# for extensions of functions defined in Base.
import Base: length, push!, show, getindex, setindex!, maximum, minimum

# objective and constraints types and functions relevant to them.
import NLSolversBase: NonDifferentiable, OnceDifferentiable, TwiceDifferentiable,
                      nconstraints, nconstraints_x, NotInplaceObjective, InplaceObjective

# var for NelderMead
import StatsBase: var

import LinearAlgebra
import LinearAlgebra: Diagonal, diag, Hermitian, Symmetric,
                      rmul!, mul!,
                      norm, normalize!,
                      diagind,
                      eigen, BLAS,
                      cholesky, Cholesky, # factorizations
                      I,
                      svd,
                      opnorm, # for safeguards in newton trust regions
                      issuccess

import SparseArrays: AbstractSparseMatrix

# exported functions and types
export optimize, maximize, # main function

       # Re-export objective types from NLSolversBase
       NonDifferentiable,
       OnceDifferentiable,
       TwiceDifferentiable,

       # Re-export constraint types from NLSolversBase
       TwiceDifferentiableConstraints,

       # I don't think these should be here [pkofod]
       OptimizationState,
       OptimizationTrace,

       # Optimization algorithms
       ## Zeroth order methods (heuristics)
       NelderMead,
       ParticleSwarm,
       SimulatedAnnealing,

       ## First order
       ### Quasi-Newton
       GradientDescent,
       BFGS,
       LBFGS,

       ### Conjugate gradient
       ConjugateGradient,

       ### Acceleration methods
       AcceleratedGradientDescent,
       MomentumGradientDescent,

       ### Nonlinear GMRES
       NGMRES,
       OACCEL,

       ## Second order
       ### (Quasi-)Newton
       Newton,

       ### Trust region
       NewtonTrustRegion,

       # Constrained
       ## Box constraints, x_i in [lb_i, ub_i]
       ### Specifically Univariate, R -> R
       GoldenSection,
       Brent,

       ### Multivariate, R^N -> R
       Fminbox,
       SAMIN,

       ## Manifold constraints
       Manifold,
       Flat,
       Sphere,
       Stiefel,

       ## Non-linear constraints
       IPNewton

include("types.jl") # types used throughout
include("Manifolds.jl") # code to handle manifold constraints
include("multivariate/precon.jl") # preconditioning functionality

# utilities
include("utilities/generic.jl") # generic utilities
include("utilities/maxdiff.jl") # find largest difference
include("utilities/update.jl")  # trace code

# Unconstrained optimization
## Grid Search
include("multivariate/solvers/zeroth_order/grid_search.jl")

## Zeroth order (Heuristic) Optimization Methods
include("multivariate/solvers/zeroth_order/nelder_mead.jl")
include("multivariate/solvers/zeroth_order/simulated_annealing.jl")
include("multivariate/solvers/zeroth_order/particle_swarm.jl")

## Quasi-Newton
include("multivariate/solvers/first_order/gradient_descent.jl")
include("multivariate/solvers/first_order/bfgs.jl")
include("multivariate/solvers/first_order/l_bfgs.jl")

## Acceleration methods
include("multivariate/solvers/first_order/accelerated_gradient_descent.jl")
include("multivariate/solvers/first_order/momentum_gradient_descent.jl")

## Conjugate gradient
include("multivariate/solvers/first_order/cg.jl")

## Newton
### Line search
include("multivariate/solvers/second_order/newton.jl")
include("multivariate/solvers/second_order/krylov_trust_region.jl")
### Trust region
include("multivariate/solvers/second_order/newton_trust_region.jl")

## Nonlinear GMRES
include("multivariate/solvers/first_order/ngmres.jl")

# Constrained optimization
## Box constraints
include("multivariate/solvers/constrained/fminbox.jl")
include("multivariate/solvers/constrained/samin.jl")

# Univariate methods
include("univariate/solvers/golden_section.jl")
include("univariate/solvers/brent.jl")
include("univariate/types.jl")
include("univariate/printing.jl")

# Line search generic code
include("utilities/perform_linesearch.jl")

# Backward compatibility
include("deprecate.jl")

# convenient user facing optimize methods
include("univariate/optimize/interface.jl")
include("multivariate/optimize/interface.jl")

# actual optimize methods
include("univariate/optimize/optimize.jl")
include("multivariate/optimize/optimize.jl")

# Convergence
include("utilities/assess_convergence.jl")
include("multivariate/solvers/zeroth_order/zeroth_utils.jl")

# Traces
include("utilities/trace.jl")

# API
include("api.jl")

## Interior point includes
include("multivariate/solvers/constrained/ipnewton/types.jl")
# Tracing
include("multivariate/solvers/constrained/ipnewton/utilities/update.jl")
# Constrained optimization
include("multivariate/solvers/constrained/ipnewton/iplinesearch.jl")
include("multivariate/solvers/constrained/ipnewton/interior.jl")
include("multivariate/solvers/constrained/ipnewton/ipnewton.jl")
# Convergence
include("multivariate/solvers/constrained/ipnewton/utilities/assess_convergence.jl")
# Traces
include("multivariate/solvers/constrained/ipnewton/utilities/trace.jl")

# Maximization convenience wrapper
include("maximize.jl")

end


text:
let
    # Test constructor errors
    @test_throws ArgumentError load_GSHHS_data(resolution=:INVALID)
    @test_throws ArgumentError load_GSHHS_data(resolution=:FULL, level=7)
    @test_throws ArgumentError load_GSHHS_data(resolution=:CRUDE, level=4)

    for res in WorldMapData.VALID_RESOLUTIONS
        for level in 1:6
            # Skip invalid products
            if res == :CRUDE && level == 4
                continue
            end

            data = load_GSHHS_data(resolution=res, level=level)
            @test length(data.shapes) > 0
        end
    end
end

let
    # Test constructor errors
    @test_throws ArgumentError load_WDBII_border_data(resolution=:INVALID)
    @test_throws ArgumentError load_WDBII_border_data(resolution=:FULL, level=4)

    for res in WorldMapData.VALID_RESOLUTIONS
        for level in 1:3
            data = load_WDBII_border_data(resolution=res, level=level)
            @test length(data.shapes) > 0
        end
    end
end

let
    # Test constructor errors
    @test_throws ArgumentError load_WDBII_river_data(resolution=:INVALID)
    @test_throws ArgumentError load_WDBII_river_data(resolution=:FULL, level=12)

    for res in WorldMapData.VALID_RESOLUTIONS
        for level in 1:11
            data = load_WDBII_river_data(resolution=res, level=level)
            @test length(data.shapes) > 0
        end
    end
end


text:
using JuliaReactToDo
using Test

@testset "JuliaReactToDo.jl" begin
    # Write your tests here.
end

max_stars_repo_name: kogad/JuliaReactToDo

max_issues_repo_name: kogad/JuliaReactToDo

max_forks_repo_name: kogad/JuliaReactToDo


text:
#=
Computes quantities related to the Gaussian linear state space model

    x_{t+1} = A x_t + C w_{t+1}

        y_t = G x_t + H v_t

The shocks {w_t} and {v_t} are iid and N(0, I)

@author : Spencer Lyon <spencer.lyon@nyu.edu>

@date : 2014-07-28

References
----------

TODO: Come back and update to match `LinearStateSpace` type from py side
TODO: Add docstrings

https://lectures.quantecon.org/jl/kalman.html

=#

doc"""
A type that describes the Gaussian Linear State Space Model
of the form:

```math
    x_{t+1} = A x_t + C w_{t+1} \\

    y_t = G x_t + H v_t
```

where ``{w_t}`` and ``{v_t}`` are independent and standard normal with dimensions
`k` and `l` respectively.  The initial conditions are ``\mu_0`` and ``\Sigma_0`` for ``x_0
\sim N(\mu_0, \Sigma_0)``. When ``\Sigma_0=0``, the draw of ``x_0`` is exactly ``\mu_0``.

#### Fields

- `A::Matrix` Part of the state transition equation.  It should be `n x n`
- `C::Matrix` Part of the state transition equation.  It should be `n x m`
- `G::Matrix` Part of the observation equation.  It should be `k x n`
- `H::Matrix` Part of the observation equation.  It should be `k x l`
- `k::Int` Dimension
- `n::Int` Dimension
- `m::Int` Dimension
- `l::Int` Dimension
- `mu_0::Vector` This is the mean of initial draw and is of length `n`
- `Sigma_0::Matrix` This is the variance of the initial draw and is `n x n` and
                    also should be positive definite and symmetric

"""
mutable struct LSS{TSampler<:MVNSampler}
    A::Matrix
    C::Matrix
    G::Matrix
    H::Matrix
    k::Int
    n::Int
    m::Int
    l::Int
    mu_0::Vector
    Sigma_0::Matrix
    dist::TSampler
end

function LSS(A::ScalarOrArray, C::ScalarOrArray, G::ScalarOrArray, H::ScalarOrArray,
             mu_0::ScalarOrArray,
             Sigma_0::Matrix=zeros(size(G, 2), size(G, 2)))
    k = size(G, 1)
    n = size(G, 2)
    m = size(C, 2)
    l = size(H, 2)

    # coerce shapes
    A = reshape(vcat(A), n, n)
    C = reshape(vcat(C), n, m)
    G = reshape(vcat(G), k, n)
    H = reshape(vcat(H), k, l)

    mu_0 = reshape([mu_0;], n)

    dist = MVNSampler(mu_0,Sigma_0)
    LSS(A, C, G, H, k, n, m, l, mu_0, Sigma_0, dist)
end

# make kwarg version
function LSS(A::ScalarOrArray, C::ScalarOrArray, G::ScalarOrArray;
             H::ScalarOrArray=zeros(size(G, 1)),
             mu_0::Vector=zeros(size(G, 2)),
             Sigma_0::Matrix=zeros(size(G, 2), size(G, 2)))
    return LSS(A, C, G, H, mu_0, Sigma_0)
end

function simulate(lss::LSS, ts_length=100)
    x = Array{Float64}(lss.n, ts_length)
    x[:, 1] = rand(lss.dist)
    w = randn(lss.m, ts_length - 1)
    v = randn(lss.l, ts_length)
    for t=1:ts_length-1
        x[:, t+1] = lss.A * x[:, t] .+ lss.C * w[:, t]
    end
    y = lss.G * x + lss.H * v

    return x, y
end

doc"""
Simulate `num_reps` observations of ``x_T`` and ``y_T`` given ``x_0 \sim N(\mu_0, \Sigma_0)``.

#### Arguments

- `lss::LSS` An instance of the Gaussian linear state space model.
- `t::Int = 10` The period that we want to replicate values for.
- `num_reps::Int = 100` The number of replications we want

#### Returns

- `x::Matrix` An `n x num_reps` matrix, where the j-th column is the j_th
              observation of ``x_T``
- `y::Matrix` An `k x num_reps` matrix, where the j-th column is the j_th
              observation of ``y_T``

"""
function replicate(lss::LSS, t::Integer, num_reps::Integer=100)
    x = Array{Float64}(lss.n, num_reps)
    v = randn(lss.l, num_reps)
    for j=1:num_reps
        x_t, _ = simulate(lss, t+1)
        x[:, j] = x_t[:, end]
    end

    y = lss.G * x + lss.H * v
    return x, y
end

replicate(lss::LSS; t::Integer=10, num_reps::Integer=100) =
    replicate(lss, t, num_reps)

struct LSSMoments
    lss::LSS
end

Base.start(L::LSSMoments) = (copy(L.lss.mu_0), copy(L.lss.Sigma_0))
Base.done(L::LSSMoments, x) = false
function Base.next(L::LSSMoments, moms)
    A, C, G, H = L.lss.A, L.lss.C, L.lss.G, L.lss.H
    mu_x, Sigma_x = moms

    mu_y, Sigma_y = G * mu_x, G * Sigma_x * G' + H * H'

    # Update moments of x
    mu_x2 = A * mu_x
    Sigma_x2 = A * Sigma_x * A' + C * C'

    (mu_x, mu_y, Sigma_x, Sigma_y), (mu_x2, Sigma_x2)
end

doc"""
Create an iterator to calculate the population mean and
variance-convariance matrix for both ``x_t`` and ``y_t``, starting at
the initial condition `(self.mu_0, self.Sigma_0)`.  Each iteration
produces a 4-tuple of items `(mu_x, mu_y, Sigma_x, Sigma_y)` for
the next period.

#### Arguments

- `lss::LSS` An instance of the Gaussian linear state space model

"""
moment_sequence(lss::LSS) = LSSMoments(lss)

doc"""
Compute the moments of the stationary distributions of ``x_t`` and
``y_t`` if possible.  Computation is by iteration, starting from the
initial conditions `lss.mu_0` and `lss.Sigma_0`

#### Arguments

- `lss::LSS` An instance of the Guassian linear state space model
- `;max_iter::Int = 200` The maximum number of iterations allowed
- `;tol::Float64 = 1e-5` The tolerance level one wishes to achieve

#### Returns

- `mu_x::Vector` Represents the stationary mean of ``x_t``
- `mu_y::Vector` Represents the stationary mean of ``y_t``
- `Sigma_x::Matrix` Represents the var-cov matrix
- `Sigma_y::Matrix` Represents the var-cov matrix

"""
function stationary_distributions(lss::LSS; max_iter=200, tol=1e-5)
    !is_stable(lss) ? error("Cannot compute stationary distribution because the system is not stable.") : nothing

    # Initialize iteration
    m = moment_sequence(lss)
    mu_x, mu_y, Sigma_x, Sigma_y = first(m)

    i = 0
    err = tol + 1.0

    for (mu_x1, mu_y, Sigma_x1, Sigma_y) in m
        i > max_iter && error("Convergence failed after $i iterations")
        i += 1
        err_mu = maximum(abs, mu_x1 - mu_x)
        err_Sigma = maximum(abs, Sigma_x1 - Sigma_x)
        err = max(err_Sigma, err_mu)
        mu_x, Sigma_x = mu_x1, Sigma_x1

        if err < tol && i > 1
            break
        end
    end

    return mu_x, mu_y, Sigma_x, Sigma_y
end

function geometric_sums(lss::LSS, bet, x_t)
    !is_stable(lss) ? error("Cannot compute geometric sum because the system is not stable.") : nothing
    I = eye(lss.n)
    S_x = (I - bet .* lss.A) \ x_t
    S_y = lss.G * S_x
    return S_x, S_y
end

doc"""
Test for stability of linear state space system.
First removes the constant row and column.

#### Arguments

- `lss::LSS` The linear state space system

#### Returns

- `stable::Bool` Whether or not the system is stable

"""
function is_stable(lss::LSS)

    # Get version of A without constant row/column
    A = remove_constants(lss)

    # Check for stability
    stable = is_stable(A)
    return stable

end

doc"""
Finds the row and column, if any,  that correspond to the constant
term in a `LSS` system and removes them to get the matrix that needs
to be checked for stability.

#### Arguments

- `lss::LSS` The linear state space system

#### Returns

- `A::Matrix` The matrix A with constant row and column removed

"""
function remove_constants(lss::LSS)
    # Get size of matrix
    A = lss.A
    n, m = size(A)
    @assert n==m

    # Sum the absolute values of each row -> Do this because we
    # want to find rows that the sum of the absolute values is 1
    row_sums_to_one = (vec(sum(abs, A, 2) - 1.0)) .< 1e-14
    is_ii_one = map(i->abs(A[i, i] - 1.0) < 1e-14, 1:n)
    not_constant_index = .!(row_sums_to_one .& is_ii_one)

    return A[not_constant_index, not_constant_index]
end


text:
# # Selective flow constraints with [PowerSimulations.jl](https://github.com/NREL/PowerSimulations.jl)

# **Originally Contributed by**: Clayton Barrows and Sourabh Dalvi

# ## Introduction

# The [Operations Problems example]](../../notebook/3_PowerSimulations_examples/sequential_simulations.ipynb)
# shows the basic building blocks of building optimization problems with PowerSimulations.jl.
# This example shows how to customize the enforcement of branch flow constraints as is common
# when trying to build large scale simulations.

# ## Dependencies
using SIIPExamples

# ### Modeling Packages
using PowerSystems
using PowerSimulations

# ### Optimization packages
# For this simple example, we can use the Cbc solver with a relatively relaxed tolerance.
using Cbc #solver
solver = optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 1, "ratioGap" => 0.5)

# ### Create a `System` from RTS-GMLC data
# We can just use the
# [parsing tabular data example.](../../notebook/2_PowerSystems_examples/parse_tabulardata.jl)
pkgpath = dirname(dirname(pathof(SIIPExamples)))
include(joinpath(pkgpath, "test", "2_PowerSystems_examples", "parse_tabulardata.jl"))

# ### Selecting flow limited lines
# Since PowerSimulations will apply constraints by component type (e.g. Line), we need to
# change the component type of the lines on which we want to enforce flow limits. So, let's
# change the device type of certain branches from Line to MonitoredLine differentiate
# treatment when we build the model. Here, we can select inter-regional lines, or lines
# above a voltage threshold.

for line in get_components(Line, sys)
    if (get_base_voltage(get_from(get_arc(line))) >= 230.0) &&
       (get_base_voltage(get_to(get_arc(line))) >= 230.0)
        #if get_area(get_from(get_arc(line))) != get_area(get_to(get_arc(line)))
        @info "Changing $(get_name(line)) to MonitoredLine"
        convert_component!(MonitoredLine, line, sys)
    end
end

# ## Build an `OperationsProblem`
uc_prob =
    UnitCommitmentProblem(sys, optimizer = solver, horizon = 24, network = DCPPowerModel)

# Let's change the formulation of the `Line` components to an unbounded flow formulation.
# This formulation still enforces Kirchoff's laws, but does not apply flow constraints.
set_branch_model!(uc_prob, :L, DeviceModel(Line, StaticLineUnbounded))

# Notice that there is no entry for `MonitoredLine` branches. So, let's add one.
construct_device!(uc_prob, :ML, DeviceModel(MonitoredLine, StaticLine))

# Solve the relaxed problem

solve!(uc_prob)


text:
using LinearAlgebra

function to_dense(
  a::AbstractArray{T, 1},
  U::AbstractArray{T, 2},
  V::AbstractArray{T, 2},
  P::AbstractArray{T, 2}
) where T
  N, J = size(U)
  K::DenseArray{T, 2} = zeros(N, N)

  p = ones(J)
  @inbounds for m in 1:N
    vm = V[m, :]
    fill!(p, 1.0)
    K[m, m] = a[m]

    @inbounds for n in m+1:N
      p = p .* P[n - 1, :]
      un = U[n, :]
      K[n, m] = sum(un .* vm .* p)
      K[m, n] = K[n, m]
    end
  end

  K
end

function matmul(
  a::AbstractArray{T, 1},
  U::AbstractArray{T, 2},
  V::AbstractArray{T, 2},
  P::AbstractArray{T, 2},
  Z::AbstractArray{T}
) where T

  N, J = size(U)
  nrhs = size(Z, 2)

  F = zeros(J, nrhs)
  Y = zeros(N, nrhs)
  Y[N, :] = a[N] .* Z[N, :]
  @inbounds for n in N-1:-1:1
    F = P[n, :] .* (F .+ U[n + 1, :] * transpose(Z[n + 1, :]))
    Y[n, :] = a[n] .* Z[n, :] + transpose(F) * V[n, :]
  end

  fill!(F, 0)
  @inbounds for n in 2:N
    F = P[n - 1, :] .* (F .+ V[n - 1, :] * transpose(Z[n - 1, :]))
    Y[n, :] .+= transpose(F) * U[n, :]
  end

  Y

end

function factor!(
  U::AbstractArray{T, 2},
  P::AbstractArray{T, 2},
  d::AbstractArray{T, 1},
  W::AbstractArray{T, 2}
) where T

  N, J = size(U)
  Sn = zeros(J, J)

  W[1, :] ./= d[1]

  @inbounds for n in 2:N
    Sn += d[n - 1] .* W[n - 1, :] * transpose(W[n - 1, :])
    Sn = P[n - 1, :] .* Sn .* transpose(P[n - 1, :])
    tmp = transpose(U[n, :]) * Sn
    d[n] -= tmp * U[n, :]
    if (d[n] <= 0)
      throw("matrix not positive definite")
    end
    W[n, :] -= transpose(tmp)
    W[n, :] ./= d[n]
  end

end

function solve!(
  U::AbstractArray{T, 2},
  P::AbstractArray{T, 2},
  d::AbstractArray{T, 1},
  W::AbstractArray{T, 2},
  Z::AbstractArray{T}
) where T

  N, J = size(U)
  nrhs = size(Z, 2)
  Fn = zeros(J, nrhs)

  @inbounds for n in 2:N
    Fn = P[n - 1, :] .* (Fn + W[n - 1, :] * transpose(Z[n - 1, :]))
    Z[n, :] -= transpose(Fn) * U[n, :]
  end

  Z ./= d

  fill!(Fn, 0)
  @inbounds for n in N-1:-1:1
    Fn = P[n, :] .* (Fn + U[n + 1, :] * transpose(Z[n + 1, :]))
    Z[n, :] -= transpose(Fn) * W[n, :]
  end

end

function dot_tril!(
  U::AbstractArray{T, 2},
  P::AbstractArray{T, 2},
  d::AbstractArray{T, 1},
  W::AbstractArray{T, 2},
  Z::AbstractArray{T}
) where T

  N, J = size(U)
  nrhs = size(Z, 2)
  Fn = zeros(J, nrhs)
  sqrtd = sqrt.(d)

  Z[1, :] .*= sqrtd[1]
  tmp = Z[1, :]

  @inbounds for n in 2:N
    Fn = P[n - 1, :] .* (Fn + W[n - 1, :] * transpose(tmp))
    tmp = sqrtd[n] .* Z[n, :]
    Z[n, :] = tmp + transpose(Fn) * U[n, :]
  end

end


text:
"""
Wrapper function for generating agent and object positions/targets. Different position functions share common inputs:

type = type of agent
    :A = agent (has velocity, subject to repulsive forces)
    :O = object (has no velocity, cannot move, agents must go around)
    :T = target (no velocity, just a projection of agent target zone)
radius = model.d/2 because model.d describes the minimum distance from agent centroid to agent centroid. Assuming that agents are circular and the same size, this means that model.d is also the diameter of the agent. Thus we use a radius of model.d/2
"""
function AgentPositionInit(model, num_agents; type="random")

    if type == "circle"
        return CirclePositions(model, num_agents)
    elseif type == "circle_object"
        return CirclePositionsObject(model, num_agents)
    elseif type == "line"
        return LinePositions(model, num_agents)
    elseif type == "centered_line_object"
        return CenteredLineObject(model, num_agents)
    elseif type == "moving_line"
        return CenteredObjectMovingLine(model, num_agents)
    elseif type == "random"
        return RandomPositions(model, num_agents)
    else
        @warn "Invalid simulation type; simulating random"
        return RandomPositions(model, num_agents)  # return random anyways
    end
end

"""
Simulation where agents start on one side of the state space and move in a vertical line from left to right.
"""
function LinePositions(model, num_agents)

    x, y = model.space.extent
    for i in 1:num_agents
        xi = 0.1*x
        yi = y - (0.1*y+0.9*y/(num_agents)*(i-1))

        pos = (xi, yi)
        vel = (0,0)
        tau = pos .+ (0.8*x, 0)
        radius = model.d/2
        color = AgentInitColor(i, num_agents)
        add_agent!(pos, model, vel, tau, color, :A, radius, model.space.extent)  # add agents
        add_agent!(tau, model, vel, tau, color, :T, radius, model.space.extent)  # add targets

    end
    return model

end

"""
Simulation with unmoving vertical line of agents in middle of state space. A moving object is moving from left to right through line of agents. Agents must move around object and attempt to reorient themselves in the vertical line.
"""
function CenteredLineObject(model, num_agents)

    x, y = model.space.extent
    for i in 1:num_agents
        xi = 0.5*x
        yi = y - (0.1*y+0.9*y/(num_agents)*(i-1))

        pos = (xi, yi)
        vel = (0,0)
        tau = pos
        radius = model.d/2
        color = AgentInitColor(i, num_agents)
        add_agent!(pos, model, vel, tau, color, :A, radius, model.space.extent)  # add agents

    end

    xio = 0.1*x
    yio = 0.5*y
    object_pos = (xio, yio)
    object_vel = (0,0)
    object_tau = (x-0.1*x, 0.5*y)
    object_radius = 0.1
    color = "#ff0000"
    add_agent!(object_pos, model, object_vel, object_tau, color, :O, object_radius, model.space.extent)  # add object
    add_agent!(object_tau, model, object_vel, object_tau, color, :T, object_radius, model.space.extent)  # add object target

    return model

end

"""
Simulation similar to "Line Positions" with object in middle of state space that agents must navigate around.
"""
function CenteredObjectMovingLine(model, num_agents)

    x, y = model.space.extent
    for i in 1:num_agents
        xi = 0.1*x
        yi = y - (0.1*y+0.9*y/(num_agents)*(i-1))

        pos = (xi, yi)
        vel = (0,0)
        tau = (0.8*x,0) .+ pos
        radius = model.d/2
        color = AgentInitColor(i, num_agents)
        add_agent!(tau, model, vel, tau, color, :T, radius, model.space.extent)  # add object target
        add_agent!(pos, model, vel, tau, color, :A, radius, model.space.extent)  # add agents

    end

    xio = 0.3*x
    yio = 0.5*y
    object_pos = (xio, yio)
    object_vel = (0,0)
    object_tau = object_pos
    object_radius = 0.2
    color = "#ff0000"
    add_agent!(object_pos, model, object_vel, object_tau, color, :O, object_radius, model.space.extent)  # add object

    return model

end

"""
Agents start around the perimeter of a circle and attempt to move to a position on the opposite side of the circle - all agents end up driving towards the center.
"""
function CirclePositions(model, num_agents)

    # determine circle params
    x, y = model.space.extent
    r = 0.9*(min(x,y)/2)

    for i in 1:num_agents

        # compute position around circle
        theta_i = (2*π/num_agents)*i
        xi = r*cos(theta_i)+x/2
        yi = r*sin(theta_i)+y/2

        xitau = r*cos(theta_i+π)+x/2
        yitau = r*sin(theta_i+π)+y/2

        # set agent params
        pos = (xi, yi)
        vel = (0,0)
        tau = (xitau, yitau)  # goal is on opposite side of circle
        #tau = (x/2,y/2)
        type = :A
        radius = model.d/2
        color = AgentInitColor(i, num_agents)
        add_agent!(pos, model, vel, tau, color, :A, radius, model.space.extent)
        add_agent!(tau, model, vel, tau, color, :T, radius, model.space.extent)
    end

    return model

end

"""
Agents start around the perimeter of a circle and attempt to move to a position on the opposite side of the circle - all agents end up driving towards the center. There is also an object in the middle.
"""
function CirclePositionsObject(model, num_agents)

    # determine circle params
    x, y = model.space.extent
    r = 0.9*(min(x,y)/2)

    for i in 1:num_agents

        # compute position around circle
        theta_i = (2*π/num_agents)*i
        xi = r*cos(theta_i)+x/2
        yi = r*sin(theta_i)-y/2

        xitau = r*cos(theta_i+π)+x/2
        yitau = r*sin(theta_i+π)+y/2

        # set agent params
        pos = (xi, yi)
        vel = (0,0)
        tau = (xitau, yitau)  # goal is on opposite side of circle
        #tau = (x/2,y/2)
        type = :A
        radius = model.d/2
        color = AgentInitColor(i, num_agents)
        add_agent!(pos, model, vel, tau, color, :A, radius, model.space.extent)
        add_agent!(tau, model, vel, tau, color, :T, radius, model.space.extent)
    end

    object_radius = 0.1
    add_agent!((x/2,y/2), model, (0,0), (x/2,y/2), "#ff0000", :O, object_radius, model.space.extent)  # add object in middle
    return model

end

"""
Agents start in random positions with random velocities and seek a random target position.
"""
function RandomPositions(model, num_agents)
    Random.seed!(42)
    for i in 1:num_agents
        pos = Tuple(rand(2))
        vel = Tuple(rand(2))
        tau = Tuple(rand(2))
        type = :A
        radius = model.d/2
        color = AgentInitColor(i, num_agents)
        add_agent!(pos, model, vel, tau, color, type, radius, model.space.extent)
    end

    return model

end

max_stars_repo_name: rmcsqrd/antfarm

max_issues_repo_name: rmcsqrd/antfarm

max_forks_repo_name: rmcsqrd/antfarm


text:
module NCFlex

include("intro.jl")

include("basics.jl")

include("mode1.jl")

end # module


text:
if length(
        lowercase(strip(get(ENV, "PREDICTMD_OPEN_PLOTS_DURING_TESTS", "")))
        ) == 0
    ENV["PREDICTMD_OPEN_PLOTS_DURING_TESTS"] = "false"
end

@debug(
    string(
        "PREDICTMD_OPEN_PLOTS_DURING_TESTS: \"",
        ENV["PREDICTMD_OPEN_PLOTS_DURING_TESTS"],
        "\"",
        )
    )


text:
function RK4!(du, u, p, update_du!, Δt::T) where T<:AbstractFloat

  # initialize derivative ponderated sum
  du_sum = zeros(eltype(u),size(u))

  # increment derivative ponderated sum
  update_du!(du,u,p,0.0)
  du_sum .+= du

  update_du!(du,u.+((Δt/2.0).*du),p,0.0)
  du_sum .+= 2.0 .* du

  update_du!(du,u.+(Δt/2.0).*du,p,0.0)
  du_sum .+= 2.0 .* du

  update_du!(du,u.+Δt.*du,p,0.0)
  du_sum .+= du

  # update u with the mean of the ponderated sum over Δt
  return (Δt/6).*du_sum .+ u
end

function RK4(u, p, update_du, Δt::T) where T<:AbstractFloat

  # increment derivative ponderated sum
  du1 = update_du(u,p,0.0)
  du2 = update_du(u.+((Δt/2.0).*du1),p,0.0)
  du3 = update_du(u.+((Δt/2.0).*du2),p,0.0)
  du4 = update_du(u.+Δt.*du3,p,0.0)
  du_sum = du1 + 2*du2 + 2*du3 + du4

  # update u with the mean of the ponderated sum over Δt
  return (Δt/6)*du_sum + u
end

function timestep_RK4_adaptative!(du, u, p, update_du!, Δt::T, e₀::T) where T<: AbstractFloat
  u1 = RK4!(du, u, p, update_du!, Δt)
  #println("RK4 u1",u1)
  uint = RK4!(du, u, p, update_du!, Δt/2)
  #println("RK4 uint",uint)
  u2 = RK4!(du, uint, p, update_du!, Δt/2)
  #println("RK4 u2",u2)

  e = abs(u2[1]-u1[1]) # error calculated on damage only
  if e < e₀
      return u1, Δt, min(Δt*abs(e₀/e),Δt*2)
  else
      timestep_RK4_adaptative(du, u, p, update_du!, float(Δt*abs(e₀/e)^2), e₀)
  end
end

function timestep_RK4_adaptative_2points(u, p, update_du, Δt::T, e₀::T) where T<: AbstractFloat
  u1 = RK4(u, p, update_du, Δt)
  #println("RK4 u1",u1)
  uint = RK4(u, p, update_du, Δt/2)
  #println("RK4 uint",uint)
  u2 = RK4(uint, p, update_du, Δt/2)
  #println("RK4 u2",u2)
  Ṡ1, σ̇ⁱξξ1, σ̇ⁱoop1, ϵ̇ⁱηη1, Ḋᵒ1, Ḋⁱ1 = u1
  Ṡ2, σ̇ⁱξξ2, σ̇ⁱoop2, ϵ̇ⁱηη2, Ḋᵒ2, Ḋⁱ2 = u2

  eD = max(abs((Ḋⁱ2-Ḋⁱ1)/Ḋⁱ2),abs((Ḋᵒ2-Ḋᵒ1)/Ḋᵒ2))
  eS = abs((Ṡ2-Ṡ1)/Ṡ2)
  eσ = max(abs((σ̇ⁱξξ2-σ̇ⁱξξ1)/σ̇ⁱξξ2),abs((σ̇ⁱoop2-σ̇ⁱoop1)/σ̇ⁱoop2))
  eϵ = abs((ϵ̇ⁱηη2-ϵ̇ⁱηη1)/ϵ̇ⁱηη2)
  e_vec = Vec(eD,eS,eσ,eϵ)
  e_normalized = e_vec./e₀
  e_norm_max, id_e_norm_max = findmax(e_normalized)

  if e_norm_max < e₀
      return u2, Δt, min(Δt*abs(e₀/e_norm_max),Δt*2)
  else
      timestep_RK4_adaptative_2points(u, p, update_du, float(Δt*abs(e₀/e_norm_max)^2), e₀)
  end
end

function compute_RK4_adaptative(u0,p,update_du,tspan,Δt_ini,e₀)
  u_vec = Vector{SVector{6,Float64}}()
  t_vec = Float64[tspan[1]]
  #u_next = similar(u0)
  cohesion_loss_flag = false
  push!(u_vec,u0)
  next_Δt = Δt_ini
  while t_vec[end] < tspan[2]
      (t_vec[end]+next_Δt > tspan[2]) && (next_Δt = tspan[2] - t_vec[end]) # prevents time overshoot
      u_next, used_Δt, next_Δt = timestep_RK4_adaptative_2points(u_vec[end], p, update_du,next_Δt,e₀)
      push!(u_vec,u_next)
      push!(t_vec,t_vec[end]+used_Δt)

      # break if D >= 1
      if any(@view(u_next[5:6]) .>= 0.98)
          cohesion_loss_flag = true
          break
      end
  end
  return t_vec, u_vec, cohesion_loss_flag
end