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

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

Cancels a contact with a specified contact ID.

# Arguments
- `contact_id`: UUID of a contact.

"""
function cancel_contact(contactId; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "DELETE",
        "/contact/$(contactId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function cancel_contact(
    contactId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "DELETE",
        "/contact/$(contactId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_config(config_data, name)
    create_config(config_data, name, params::Dict{String,<:Any})

Creates a Config with the specified configData parameters. Only one type of configData can
be specified.

# Arguments
- `config_data`: Parameters of a Config.
- `name`: Name of a Config.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: Tags assigned to a Config.
"""
function create_config(configData, name; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "POST",
        "/config",
        Dict{String,Any}("configData" => configData, "name" => name);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_config(
    configData,
    name,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/config",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("configData" => configData, "name" => name), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Creates a DataflowEndpoint group containing the specified list of DataflowEndpoint objects.
The name field in each endpoint is used in your mission profile DataflowEndpointConfig to
specify which endpoints to use during a contact. When a contact uses multiple
DataflowEndpointConfig objects, each Config must match a DataflowEndpoint in the same group.

# Arguments
- `endpoint_details`: Endpoint details of each endpoint in the dataflow endpoint group.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: Tags of a dataflow endpoint group.
"""
function create_dataflow_endpoint_group(
    endpointDetails; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "POST",
        "/dataflowEndpointGroup",
        Dict{String,Any}("endpointDetails" => endpointDetails);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_dataflow_endpoint_group(
    endpointDetails,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/dataflowEndpointGroup",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("endpointDetails" => endpointDetails), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_mission_profile(dataflow_edges, minimum_viable_contact_duration_seconds, name, tracking_config_arn)
    create_mission_profile(dataflow_edges, minimum_viable_contact_duration_seconds, name, tracking_config_arn, params::Dict{String,<:Any})

Creates a mission profile.  dataflowEdges is a list of lists of strings. Each lower level
list of strings has two elements: a from ARN and a to ARN.

# Arguments
- `dataflow_edges`: A list of lists of ARNs. Each list of ARNs is an edge, with a from
  Config and a to Config.
- `minimum_viable_contact_duration_seconds`: Smallest amount of time in seconds that
  you’d like to see for an available contact. AWS Ground Station will not present you with
  contacts shorter than this duration.
- `name`: Name of a mission profile.
- `tracking_config_arn`: ARN of a tracking Config.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"contactPostPassDurationSeconds"`: Amount of time after a contact ends that you’d like
  to receive a CloudWatch event indicating the pass has finished.
- `"contactPrePassDurationSeconds"`: Amount of time prior to contact start you’d like to
  receive a CloudWatch event indicating an upcoming pass.
- `"tags"`: Tags assigned to a mission profile.
"""
function create_mission_profile(
    dataflowEdges,
    minimumViableContactDurationSeconds,
    name,
    trackingConfigArn;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/missionprofile",
        Dict{String,Any}(
            "dataflowEdges" => dataflowEdges,
            "minimumViableContactDurationSeconds" => minimumViableContactDurationSeconds,
            "name" => name,
            "trackingConfigArn" => trackingConfigArn,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_mission_profile(
    dataflowEdges,
    minimumViableContactDurationSeconds,
    name,
    trackingConfigArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/missionprofile",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "dataflowEdges" => dataflowEdges,
                    "minimumViableContactDurationSeconds" =>
                        minimumViableContactDurationSeconds,
                    "name" => name,
                    "trackingConfigArn" => trackingConfigArn,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    delete_config(config_id, config_type)
    delete_config(config_id, config_type, params::Dict{String,<:Any})

Deletes a Config.

# Arguments
- `config_id`: UUID of a Config.
- `config_type`: Type of a Config.

"""
function delete_config(
    configId, configType; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "DELETE",
        "/config/$(configType)/$(configId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_config(
    configId,
    configType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "DELETE",
        "/config/$(configType)/$(configId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes a dataflow endpoint group.

# Arguments
- `dataflow_endpoint_group_id`: UUID of a dataflow endpoint group.

"""
function delete_dataflow_endpoint_group(
    dataflowEndpointGroupId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "DELETE",
        "/dataflowEndpointGroup/$(dataflowEndpointGroupId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_dataflow_endpoint_group(
    dataflowEndpointGroupId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "DELETE",
        "/dataflowEndpointGroup/$(dataflowEndpointGroupId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes a mission profile.

# Arguments
- `mission_profile_id`: UUID of a mission profile.

"""
function delete_mission_profile(
    missionProfileId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "DELETE",
        "/missionprofile/$(missionProfileId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_mission_profile(
    missionProfileId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "DELETE",
        "/missionprofile/$(missionProfileId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Describes an existing contact.

# Arguments
- `contact_id`: UUID of a contact.

"""
function describe_contact(contactId; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "GET",
        "/contact/$(contactId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_contact(
    contactId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "GET",
        "/contact/$(contactId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_config(config_id, config_type)
    get_config(config_id, config_type, params::Dict{String,<:Any})

Returns Config information. Only one Config response can be returned.

# Arguments
- `config_id`: UUID of a Config.
- `config_type`: Type of a Config.

"""
function get_config(configId, configType; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "GET",
        "/config/$(configType)/$(configId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_config(
    configId,
    configType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "GET",
        "/config/$(configType)/$(configId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns the dataflow endpoint group.

# Arguments
- `dataflow_endpoint_group_id`: UUID of a dataflow endpoint group.

"""
function get_dataflow_endpoint_group(
    dataflowEndpointGroupId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "GET",
        "/dataflowEndpointGroup/$(dataflowEndpointGroupId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_dataflow_endpoint_group(
    dataflowEndpointGroupId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "GET",
        "/dataflowEndpointGroup/$(dataflowEndpointGroupId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    get_minute_usage(month, year)
    get_minute_usage(month, year, params::Dict{String,<:Any})

Returns the number of minutes used by account.

# Arguments
- `month`: The month being requested, with a value of 1-12.
- `year`: The year being requested, in the format of YYYY.

"""
function get_minute_usage(month, year; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "POST",
        "/minute-usage",
        Dict{String,Any}("month" => month, "year" => year);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_minute_usage(
    month,
    year,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/minute-usage",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("month" => month, "year" => year), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a mission profile.

# Arguments
- `mission_profile_id`: UUID of a mission profile.

"""
function get_mission_profile(
    missionProfileId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "GET",
        "/missionprofile/$(missionProfileId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_mission_profile(
    missionProfileId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "GET",
        "/missionprofile/$(missionProfileId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a satellite.

# Arguments
- `satellite_id`: UUID of a satellite.

"""
function get_satellite(satelliteId; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "GET",
        "/satellite/$(satelliteId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function get_satellite(
    satelliteId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "GET",
        "/satellite/$(satelliteId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a list of Config objects.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of Configs returned.
- `"nextToken"`: Next token returned in the request of a previous ListConfigs call. Used to
  get the next page of results.
"""
function list_configs(; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "GET", "/config"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_configs(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "GET", "/config", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    list_contacts(end_time, start_time, status_list)
    list_contacts(end_time, start_time, status_list, params::Dict{String,<:Any})

Returns a list of contacts. If statusList contains AVAILABLE, the request must include
groundStation, missionprofileArn, and satelliteArn.

# Arguments
- `end_time`: End time of a contact.
- `start_time`: Start time of a contact.
- `status_list`: Status of a contact reservation.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"groundStation"`: Name of a ground station.
- `"maxResults"`: Maximum number of contacts returned.
- `"missionProfileArn"`: ARN of a mission profile.
- `"nextToken"`: Next token returned in the request of a previous ListContacts call. Used
  to get the next page of results.
- `"satelliteArn"`: ARN of a satellite.
"""
function list_contacts(
    endTime, startTime, statusList; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "POST",
        "/contacts",
        Dict{String,Any}(
            "endTime" => endTime, "startTime" => startTime, "statusList" => statusList
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_contacts(
    endTime,
    startTime,
    statusList,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/contacts",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "endTime" => endTime,
                    "startTime" => startTime,
                    "statusList" => statusList,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a list of DataflowEndpoint groups.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of dataflow endpoint groups returned.
- `"nextToken"`: Next token returned in the request of a previous
  ListDataflowEndpointGroups call. Used to get the next page of results.
"""
function list_dataflow_endpoint_groups(; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "GET",
        "/dataflowEndpointGroup";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_dataflow_endpoint_groups(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "GET",
        "/dataflowEndpointGroup",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a list of ground stations.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of ground stations returned.
- `"nextToken"`: Next token that can be supplied in the next call to get the next page of
  ground stations.
- `"satelliteId"`: Satellite ID to retrieve on-boarded ground stations.
"""
function list_ground_stations(; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "GET", "/groundstation"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_ground_stations(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "GET",
        "/groundstation",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a list of mission profiles.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of mission profiles returned.
- `"nextToken"`: Next token returned in the request of a previous ListMissionProfiles call.
  Used to get the next page of results.
"""
function list_mission_profiles(; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "GET", "/missionprofile"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_mission_profiles(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "GET",
        "/missionprofile",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a list of satellites.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: Maximum number of satellites returned.
- `"nextToken"`: Next token that can be supplied in the next call to get the next page of
  satellites.
"""
function list_satellites(; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "GET", "/satellite"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function list_satellites(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "GET", "/satellite", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

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

Returns a list of tags for a specified resource.

# Arguments
- `resource_arn`: ARN of a resource.

"""
function list_tags_for_resource(
    resourceArn; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "GET",
        "/tags/$(resourceArn)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags_for_resource(
    resourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "GET",
        "/tags/$(resourceArn)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    reserve_contact(end_time, ground_station, mission_profile_arn, satellite_arn, start_time)
    reserve_contact(end_time, ground_station, mission_profile_arn, satellite_arn, start_time, params::Dict{String,<:Any})

Reserves a contact using specified parameters.

# Arguments
- `end_time`: End time of a contact.
- `ground_station`: Name of a ground station.
- `mission_profile_arn`: ARN of a mission profile.
- `satellite_arn`: ARN of a satellite
- `start_time`: Start time of a contact.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: Tags assigned to a contact.
"""
function reserve_contact(
    endTime,
    groundStation,
    missionProfileArn,
    satelliteArn,
    startTime;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/contact",
        Dict{String,Any}(
            "endTime" => endTime,
            "groundStation" => groundStation,
            "missionProfileArn" => missionProfileArn,
            "satelliteArn" => satelliteArn,
            "startTime" => startTime,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function reserve_contact(
    endTime,
    groundStation,
    missionProfileArn,
    satelliteArn,
    startTime,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/contact",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "endTime" => endTime,
                    "groundStation" => groundStation,
                    "missionProfileArn" => missionProfileArn,
                    "satelliteArn" => satelliteArn,
                    "startTime" => startTime,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    tag_resource(resource_arn, tags)
    tag_resource(resource_arn, tags, params::Dict{String,<:Any})

Assigns a tag to a resource.

# Arguments
- `resource_arn`: ARN of a resource tag.
- `tags`: Tags assigned to a resource.

"""
function tag_resource(resourceArn, tags; aws_config::AbstractAWSConfig=global_aws_config())
    return groundstation(
        "POST",
        "/tags/$(resourceArn)",
        Dict{String,Any}("tags" => tags);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function tag_resource(
    resourceArn,
    tags,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "POST",
        "/tags/$(resourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("tags" => tags), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

Deassigns a resource tag.

# Arguments
- `resource_arn`: ARN of a resource.
- `tag_keys`: Keys of a resource tag.

"""
function untag_resource(
    resourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "DELETE",
        "/tags/$(resourceArn)",
        Dict{String,Any}("tagKeys" => tagKeys);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function untag_resource(
    resourceArn,
    tagKeys,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "DELETE",
        "/tags/$(resourceArn)",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("tagKeys" => tagKeys), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_config(config_data, config_id, config_type, name)
    update_config(config_data, config_id, config_type, name, params::Dict{String,<:Any})

Updates the Config used when scheduling contacts. Updating a Config will not update the
execution parameters for existing future contacts scheduled with this Config.

# Arguments
- `config_data`: Parameters of a Config.
- `config_id`: UUID of a Config.
- `config_type`: Type of a Config.
- `name`: Name of a Config.

"""
function update_config(
    configData,
    configId,
    configType,
    name;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "PUT",
        "/config/$(configType)/$(configId)",
        Dict{String,Any}("configData" => configData, "name" => name);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_config(
    configData,
    configId,
    configType,
    name,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "PUT",
        "/config/$(configType)/$(configId)",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("configData" => configData, "name" => name), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Updates a mission profile. Updating a mission profile will not update the execution
parameters for existing future contacts.

# Arguments
- `mission_profile_id`: UUID of a mission profile.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"contactPostPassDurationSeconds"`: Amount of time after a contact ends that you’d like
  to receive a CloudWatch event indicating the pass has finished.
- `"contactPrePassDurationSeconds"`: Amount of time after a contact ends that you’d like
  to receive a CloudWatch event indicating the pass has finished.
- `"dataflowEdges"`: A list of lists of ARNs. Each list of ARNs is an edge, with a from
  Config and a to Config.
- `"minimumViableContactDurationSeconds"`: Smallest amount of time in seconds that you’d
  like to see for an available contact. AWS Ground Station will not present you with contacts
  shorter than this duration.
- `"name"`: Name of a mission profile.
- `"trackingConfigArn"`: ARN of a tracking Config.
"""
function update_mission_profile(
    missionProfileId; aws_config::AbstractAWSConfig=global_aws_config()
)
    return groundstation(
        "PUT",
        "/missionprofile/$(missionProfileId)";
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_mission_profile(
    missionProfileId,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return groundstation(
        "PUT",
        "/missionprofile/$(missionProfileId)",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
using Pkg
Pkg.activate(@__DIR__)
using FileIO
using DataFrames
using SigmaRidgeRegression
using Distributions
using LaTeXStrings
using Plots
using StatsPlots
using PGFPlotsX

pgfplotsx()

empty!(PGFPlotsX.CUSTOM_PREAMBLE)
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\usepackage{amsmath}")
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\usepackage{amssymb}")
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\usepackage{bm}")
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\newcommand{\risk}[1]{\bm{R}(#1)}")
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\usepackage[bbgreekl]{mathbbol}")
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\newcommand{\sigmacv}{\bbsigma}")
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\newcommand{\bSigma}{\bm{\Sigma}}")
push!(PGFPlotsX.CUSTOM_PREAMBLE, raw"\newcommand{\bw}{\bm{w}}")

sim_path = joinpath(@__DIR__, "simulation_results")

all_files = FileIO.load.(joinpath.(sim_path, readdir(sim_path)))
all_tuples = vcat((x["res"] for x in all_files)...)

df = DataFrame(all_tuples)
df.n = getfield.(df.sim, :ntrain)

summary_f = x -> mean(x) .- 25 #25 is noise variance

gdf = groupby(df, [:cov,:n ,:K]) |>
      df -> combine(df, :mse_sigma =>  summary_f => :mse_sigma,
                        :mse_single => summary_f  => :mse_single,
                        :mse_multi => summary_f  => :mse_multi,
                        :mse_glasso => summary_f  => :mse_glasso,
                        :mse_bayes => summary_f  => :mse_bayes,
                        nrow) |>
      df -> groupby(df, [:cov,:n])

function f_tbl(i)
    return [gdf[i].mse_single gdf[i].mse_glasso gdf[i].mse_multi gdf[i].mse_sigma gdf[i].mse_bayes]
end

_cols = [:steelblue :green :orange :purple :grey]
_markers = [:utriangle :dtriangle :diamond :pentagon :circle]
_labels = ["Single Ridge" "Group Lasso" "Multi Ridge" L"\sigmacv\textrm{-Ridge}" "Bayes"]
_linestyles = [:dot :dashdot :dashdotdot :solid :dash]

plot_params = (
    frame=:box,
    grid=nothing,
    color=_cols,
    background_color_legend=:transparent,
    foreground_color_legend=:transparent,
    thickness_scaling=2.3,
    markershape=_markers,
    ylabel=L"\mathbb{E}[\risk{\widehat{\bw}}] - \sigma^2",
    linestyle=_linestyles,
    xlabel=L"K",
    xscale=:log2,
    markeralpha=0.6,
    size=(550, 440),
)

idx1 = (cov=AR1Design{Int64}(800, 0.8), n=400)
pl1 = plot(
    gdf[idx1].K,
    f_tbl(idx1);
    label=_labels,
    legend=:topleft,
    title=L"\bSigma=\textrm{AR}(0.8),\;n=p/2",
    ylim=(0, 795),
    plot_params...,
)

idx2 = (cov=AR1Design{Int64}(800, 0.8), n=800)
pl2 = plot(
    gdf[idx2].K,
    f_tbl(idx2);
    label=nothing,
    title=L"\bSigma=\textrm{AR}(0.8),\;n=p",
    ylim=(0, 285),
    plot_params...,
)

idx3 = (cov=AR1Design{Int64}(800, 0.8), n=1600)
pl3 = plot(
    gdf[idx3].K,
    f_tbl(idx3);
    label=nothing,
    title=L"\bSigma=\textrm{AR}(0.8),\;n=2p",
    ylim=(0, 55),
    plot_params...,
)

idx4 = (cov=IdentityCovarianceDesign{Int64}(800), n=400)
pl4 = plot(
    gdf[idx4].K,
    f_tbl(idx4);
    label=nothing,
    title=L"\bSigma=I,\; n=p/2",
    legend=:topleft,
    ylim=(0, 795),
    plot_params...,
)

idx5 = (cov=IdentityCovarianceDesign{Int64}(800), n=800)
pl5 = plot(
    gdf[idx5].K,
    f_tbl(idx5);
    label=nothing,
    title=L"\bSigma=I,\; n=p",
    ylim=(0, 285),
    plot_params...,
)

idx6 = (cov=IdentityCovarianceDesign{Int64}(800), n=1600)
pl6 = plot(
    gdf[6].K,
    f_tbl(6);
    label=nothing,
    title=L"\bSigma=I,\; n=2p",
    ylim=(0, 55),
    plot_params...,
)

savefig(pl1, "simulations_ar_phalf.tikz")
savefig(pl2, "simulations_ar_p.tikz")
savefig(pl3, "simulations_ar_ptwice.tikz")

savefig(pl4, "simulations_id_phalf.tikz")
savefig(pl5, "simulations_id_p.tikz")
savefig(pl6, "simulations_id_ptwice.tikz")

ext: jl


text:
module day6

readInput() = split.(readlines(joinpath(@__DIR__, "input.txt")), ')')

mutable struct Node
    name::Symbol
    parent::Union{Nothing, Node}
    children::Vector{Node}
end
Base.show(io::IO, n::Node) = print(io, n.name)

function makeTree(input)
    d = Dict{Symbol, Node}()
    for line in input
        leftSym = Symbol(first(line))
        left = get!(d, leftSym, Node(leftSym, nothing, []))
        rightSym = Symbol(last(line))
        right = get!(d, rightSym, Node(rightSym, left, []))
        right.parent = left
        push!(left.children, right)
    end
    d
end

function part1(input)
    d = makeTree(input)
    nbOrbits = 0
    for n in values(d)
        p = n
        while p.parent !== nothing
            p = p.parent
            nbOrbits += 1
        end
    end
    nbOrbits
end

function part2(input)
    d = makeTree(input)

    YOU = d[:YOU]
    SAN = d[:SAN]

    # List all parents from "YOU" with their distance
    parentNodes = Dict{Node, Int}()
    p, i = YOU, 0
    while p.parent !== nothing
        push!(parentNodes, p.parent => i)
        p = p.parent
        i += 1
    end

    # Iterate each parent from "SAN", counting the distance,
    # while they're not in the list of "YOU"'s parents
    p, i = SAN, 0
    while !(p.parent in keys(parentNodes))
        p = p.parent
        i += 1
    end

    return i + parentNodes[p.parent]
end

end


text:
module MultiFieldFEOperatorsTests

using Gridap.Arrays
using Gridap.Algebra
using Gridap.Geometry
using Gridap.FESpaces
using Gridap.Fields
using Gridap.MultiField
using Gridap.CellData
using SparseArrays
using Test
using LinearAlgebra
using Gridap.ReferenceFEs

using Gridap.MultiField

order = 2

domain = (0,1,0,1)
partition = (3,3)
model = CartesianDiscreteModel(domain,partition)

degree = order
Ω = get_triangulation(model)
dΩ = Measure(Ω,degree)

sdegree = order
Γ = SkeletonTriangulation(model)
dΓ = Measure(Γ,sdegree)

V = TestFESpace(model,ReferenceFE(lagrangian,Float64,order);conformity=:H1)
Q = TestFESpace(model,ReferenceFE(lagrangian,Float64,order-1),conformity=:L2)

U = TrialFESpace(V)
P = TrialFESpace(Q)

Y = MultiFieldFESpace([V,Q])
X = MultiFieldFESpace([U,P])

a((u,p),(v,q)) =
  ∫( v*u + v*p - q*p )*dΩ +
  ∫( jump(v)*mean(u) + jump(∇(q))⋅jump(∇(p)) )*dΓ

l((v,q)) = ∫( v*4 + q )*dΩ

op = AffineFEOperator(a,l,X,Y)

xh = zero(X)
b = residual(op,xh)
A = jacobian(op,xh)
test_fe_operator(op,get_free_dof_values(xh),b)

r((u,p),(v,q)) = ∫( v*(u*u) + v*p*u - q*p - v*4 + q )*dΩ
j((u,p),(du,dp),(v,q)) = ∫(2*v*u*du + v*dp*u + v*p*du - q*dp)*dΩ

op = FEOperator(r,j,X,Y)
xh = zero(X)
b = residual(op,xh)
A = jacobian(op,xh)
test_fe_operator(op,get_free_dof_values(xh),b)

op_auto = FEOperator(r,X,Y)
A_auto = jacobian(op_auto,xh)
@test A ≈ A_auto

r_const((u,p),(v,q)) = -1.0 * (∫( v*1.0 )*dΩ)
op_const = FEOperator(r_const,j,X,Y)
b_const = residual(op_const,xh)
test_fe_operator(op_const,get_free_dof_values(xh),b_const)

end # module


text:
module DMatTest
using Base.Test
using Quantum

xb = basis(:X,[1:3])
xbplus = basis(:X,[1:4])
xbminus = basis(:X,[0:3])

d = dmat(eye(3), xb)
@test d==d''
@test d[:,:]==d.coeffs
@test d*ket(:X,2) == dvec([0.0,1.0,0.0], xb)

@test d+ket(:X,4)*bra(:X,4) == dmat(eye(4),xbplus)
@test d+ket(:X,4)*bra(:X,3) == dmat([eye(3), [0 0 1]],xbplus, xb')
@test d+ket(:X,3)*bra(:X,4) == dmat([eye(3) [0,0,1]],xb, xbplus')
@test d+ket(:X,3)*bra(:X,3) == dmat((coeff=eye(3); coeff[3,3]=2.0; coeff),xb)

@test ket(:X,0)*bra(:X,0)+d == dmat(eye(4),xbminus)
@test ket(:X,0)*bra(:X,1)+d == dmat([[1 0 0], eye(3)],xbminus, xb')
@test ket(:X,1)*bra(:X,0)+d == dmat([[1,0,0] eye(3)],xb, xbminus')
@test ket(:X,1)*bra(:X,1)+d == dmat((coeff=eye(3); coeff[1,1]=2.0; coeff),xb)

@test d+d==2*d
@test isdual(d,d')
@test map(x->x*2, d)==d+d
@test commutator(d,d)==dmat(zeros(3,3), xb)

end


text:
#ДАНО: Робот - в произвольной клетке поля (без внутренних перегородок и маркеров)
#РЕЗУЛЬТАТ: Робот - в исходном положении, и все клетки по периметру внешней рамки промакированы

function mark_perimetr!(r)
    go_ugol!(r,(Sud,West))
    for side in (Nord,Ost,Sud,West)
        go_to_marker!(r,side)
    end

end

function go_to_marker!(r,side)
    while !isborder(r,side)
        putmarker!(r)
        move!(r,side)
    end
end

function movements!(r,side)
    while !isborder(r,side)
        move!(r,side)
    end
end

function go_ugol!(r, side::NTuple{2,HorizonSide})
    movements!(r,side[1])
    movements!(r,side[2])
end


text:
if Pkg.installed("CUDArt") != nothing
    using CUDArt
    using CUBLAS
    using CUSPARSE

    import Base: A_mul_B!

    axpy!{T<:Number}(α::T, x::CudaVector{T}, y::CudaVector{T}) =
        CUBLAS.axpy!(α, x, y)

    A_mul_B!{T<:Number}(α::T, A::CudaMatrix{T},
                        x::CudaVector{T},
                        β::T, y::CudaVector{T}) =
                            CUBLAS.gemv!('N', α, A, x, β, y)

    A_mul_B!{T<:Number}(α::T, A::AbstractCudaSparseMatrix{T},
                        x::CudaVector{T},
                        β::T, y::CudaVector{T}) =
                            CUSPARSE.mv!('N', α, A, x, β, y, 'O')

    include("cu_banded.jl")

    KindOfVector = Union{AbstractVector,CudaVector}
    KindOfMatrix = Union{AbstractMatrix,CudaMatrix,CudaBandedMatrix,AbstractCudaSparseMatrix}

    import Base: sub
    function sub{T}(M::CUDArt.CudaVector{T}, i::UnitRange)
        m = size(M,1)
        ptr = M.ptr + (minimum(i)-1)*m*sizeof(T)
        CudaVector{T}(ptr, (length(i),), M.dev)
    end

    function sub{T}(M::CUDArt.CudaMatrix{T}, ::Colon, j::Int)
        m = size(M,1)
        ptr = M.ptr + (j-1)*m*sizeof(T)
        CudaVector{T}(ptr, (m,), M.dev)
    end

    function sub{T}(M::CUDArt.CudaMatrix{T}, ::Colon, j::UnitRange)
        m = size(M,1)
        ptr = M.ptr + (minimum(j)-1)*m*sizeof(T)
        CudaMatrix{T}(ptr, (m,length(j)), M.dev)
    end

    upload(A::BandedMatrix) = CudaBandedMatrix(A)
    upload(A::AbstractSparseMatrix) = CudaSparseMatrixCSR(A)
    upload(A::AbstractMatrix) = CudaArray(A)

    export sub, upload
end


text:
using Flux, DataDeps, BSON, WordTokenizers
include("./NER_datadeps.jl")
include("./sequence_labelling.jl")

const NER_Char_UNK = '¿'
const NER_Word_UNK = "<UNK>"

struct NERmodel{M}
    model::M
end

function load_model_dicts(filepath)
    labels = BSON.load(joinpath(filepath, "labels.bson"))[:labels]
    chars_idx = BSON.load(joinpath(filepath, "char_to_embed_idx.bson"))[:get_char_index]
    words_idx = BSON.load(joinpath(filepath, "word_to_embed_idx.bson"))[:get_word_index]

    return remove_ner_label_prefix.([labels...]), chars_idx, words_idx
end

NERTagger() = NERTagger(datadep"NER Model Weights")

function NERTagger(weights_path)
    labels, chars_idx, words_idx = load_model_dicts(datadep"NER Model Dicts")
    model = BiLSTM_CNN_CRF_Model(labels, chars_idx, words_idx, chars_idx[NER_Char_UNK], words_idx[NER_Word_UNK], weights_path)
    NERmodel(model)
end

function (a::NERmodel)(sentence::String)
    a(tokenize(sentence))
    # a(tokenize(Languages.English(), sentence))
end

function (a::NERmodel)(tokens::Array{String,1})
    input_oh = [onehotinput(a.model, token) for token in tokens]
    return (a.model)(input_oh)
end

function remove_ner_label_prefix(str)
    str == "O" && return str
    str = str[3:end]
end


text:
# Evaluation methods for additively separable functions

import Base.Cartesian.lreplace

"""Given an array of expressions, returns the array of negation of expressions"""
function negate_exprs(exprs::Array)::Array
    negated_exprs = []
    for expr in exprs
        if isa(expr, Real)
            push!(negated_exprs, -expr)
        else
            push!(negated_exprs, Expr(:call, :-, expr))
        end
    end
    return negated_exprs
end

"""Return the variable indices involved in an expression"""
function get_vars_expr(expr::Expr)
    vars = Set()
    exprs_to_process = [expr]               #stores remaining (sub)expressions in expr that need to be preocessed
    while !isempty(exprs_to_process)
        cur_expr = pop!(exprs_to_process)
        if cur_expr.head == :call           #if the current expression is a "call" type, e.g., x + y or 2*x, ...
            for i in 2:length(cur_expr.args)
                if isa(cur_expr.args[i], Expr)  #if an argument is exprresion, it is added to the list to be processed
                    push!(exprs_to_process, cur_expr.args[i])
                end
            end
        elseif cur_expr.head == :ref        #if the current expression is a "reference" type, e.g., x[i]
            if cur_expr.args[1] != :x
                error("Variables in expression not supported (", expr, ")")
            end
            push!(vars, cur_expr.args[2]) # found variable, store index
        else
            error("Expression in constraint not supported (", expr, ")")
        end
    end
    return vars
end

"""Decomposes a given expression into separable terms.

Input:
expr: the expression.

Output:
An array that stores decomposed parts (expressions) of the constraint.
These parts are separated by + sing, e.g., 3x[1] - x[1]^2 + sin(x[2]) - 4 <= 0, will be stored in an array with 4 elements for the lhs.
If the constraint is not additively separable, throws error.
"""

separate_additively(expr::Real)::Array = [expr]

function separate_additively(expr::Expr)::Array
    # Examine the expression tree: first split (in)equalities and then check if
    # each term separated by a + or - uses only one type of variable
    println(expr.head, " -- ", expr.args, " -- ", expr.typ)
    if expr.head == :call
        # println("Call")
        # (In)equality or non-unary -
        if expr.args[1] in [:(<=), :(==), :(>=)] || (expr.args[1] == :- && length(expr.args) >= 3)
            # If (in)equality, move right-hand side to left-hand side by negating it
            # If subtraction, negate second expression
            exprs = []
            append!(exprs, separate_additively(expr.args[2]))
            append!(exprs, negate_exprs(separate_additively(expr.args[3])))
            return exprs
        # Non-unary +
        elseif expr.args[1] in [:+] && length(expr.args) >= 3
            exprs = []
            for i in 2:length(expr.args)
                append!(exprs, separate_additively(expr.args[i]))
            end
            return exprs
        # Unary +
        elseif expr.args[1] in [:+] # unary; binary operator already checked
            return separate_additively(expr.args[2])
        # Unary -
        elseif expr.args[1] in [:-] # unary; binary operator already checked
            return negate_exprs(separate_additively(expr.args[2]))
        # Process expression as a single component; must only contain one type of variable
        else
            vars = get_vars_expr(expr)
            if length(vars) >= 2
                error("Non-additively separable constraint in model")
            end
            return [expr]
        end
    elseif expr.head == :comparison
        error("Only one-sided constraints are supported")  # to make DD construction easier
    elseif expr.head == :ref
        return [expr]  # isolated variable
    else
        error("Expression in constraint not supported (", expr, ")")
    end
end

"""
Function: Returns the sense of a given expression in form of an (in)equality.
Returns error if the expression is not (in)equality
"""

function get_constraint_sense(expr::Expr)
    if expr.head == :call && expr.args[1] in [:(<=), :(==), :(>=)]
        return a.args[1]            #Sybmbol for the (in)equality sense
    else
        error("Expression not in constraint form (", expr, ")")
    end
end

#************************************************************************
#*************************************************************************
#*************************************************************************
"""Evaluate a univariate expression replacing the variable by the given value"""
function eval_var(expr::Expr, val::Real)
    # Replace references by the value
    if expr.head == :ref        #if the expression is composed of a single variable assigns the value
        return val
    else                        #otherwise decomposes the expression down to variables
        copy_expr = copy(expr)
        exprs_to_process = [copy_expr]
        while !isempty(exprs_to_process)
            cur_expr = pop!(exprs_to_process)
            if cur_expr.head == :call
                for i in 2:length(cur_expr.args)
                    if isa(cur_expr.args[i], Expr)
                        if cur_expr.args[i].head == :ref
                            cur_expr.args[i] = val          #replacing the variable with its value
                        else
                            push!(exprs_to_process, cur_expr.args[i])
                        end
                    end
                end
            else
                error("Expression in constraint not supported (", expr, ")")
            end
        end
        return eval(copy_expr)
    end
end

"""
TODO: Another method to evaluate a given expression, where we allow several variables (for nonseparable case!)
"""

"""
Function: calculates min and max value of a univariate expression over a given domain

Input:
expr: Expression
lb: lower bound
ub: upper bound

Output:
min_val
max_val
"""
function min_max_calculator(expr::Expr, doms::Array{Range})
    min_val = Inf
    max_val = -Inf
    for j in doms
        val = eval_var(expr, j)
        min_val = min(val, min_val)
        max_val = max(val, max_val)
    end
    return min_val, max_val
end

#An alternative method, where it takes a univarate function as input and computes the min and max over given domain
function min_max_calculator(func::Function, doms::Array{Range})
    min_val = Inf
    max_val = -Inf
    for j in doms
        val = func(j)
        min_val = min(val, min_val)
        max_val = max(val, max_val)
    end
    return min_val, max_val
end

"""Oracle that yields decomposition terms of a given function"""
mutable struct SeparableFunctionEvaluation
    separate_exprs::Array{Expr}     # each element stores the univariate expression for a variable
    separate_functions::Array{Function} # each element stores the univariate function for a variable
    constant::Real         # constant term of function
#    values::Array{Dict}    # values of each term per variable-value pair, each element corresponding to a variable (depends on the variables domain)
#    max_vals::Array{Real}  # maximum values of each term per variable (depends on the variables domain)
#    min_vals::Array{Real}  # minimum values of each term per variable (depends on the variables domain)
end

"""
Function: Returns decomposition terms of constraints of a model

Input:
m: the model

Output:
evals: An array of function specifications for constraints
"""

function evaluate_separable_constraints(m::Model)::Array{SeparableFunctionEvaluation}
    d = JuMP.NLPEvaluator(m)        #obtains an NLP evaluator object from a JuMP model, which enables query of function characteristics in the model
    MathProgBase.initialize(d, [:ExprGraph])    #enables query of the functions of the model in their expression graph form

    # Gather parts for separable constraints
    nconstrs = MathProgBase.numconstr(m)
    nvars = MathProgBase.numvar(m)
    evals = Array{SeparableFunctionEvaluation}(undef, nconstrs)

    for i in 1:nconstrs
        expr = MathProgBase.constr_expr(d, i)       #gets the expression of the ith constraint
        parts = separate_additively(expr)         #gets the array of decomposed part of the constraint

        # Put all constraints in f(x) <= 0 form by negating the lhs when >=.
        con_sense = get_constraint_sense(expr)
        if con_sense == :>=
            parts = negate_exprs(parts)
        # elseif con_sense == :==           #need to implement for == case: create two constraints with <=...
        end

        # Separate constant part from expressions
        constant_indices = (j for (j, p) in enumerate(parts) if isa(p, Real))
        if isempty(constant_indices)
            constant = 0
        else
            constant = sum(parts[j] for j in constant_indices)
            deleteat!(parts, constant_indices)
        end

        # Organize parts per variables
        var_parts = Array{Expr}(undef, nvars)
        for p in parts
            v = first(get_vars_expr(p))
            if !isassigned(var_parts, v)
                var_parts[v] = p
            else
                var_parts[v] = Expr(:call, :+, var_parts[v], p)
            end
        end

        # Create function corresponding to each univariate expression
        function_parts = Array{Function}(undef, nvars)
        for j in 1:nvars
            if isassigned(var_parts, j)
                function_parts[j] = (xx::Int64) -> eval_var(var_parts[j], xx)
            end
        end

        #Computes the attributes corresponding to function value over variable domain
        #Assumes the domain consists of all integer values within the bounds of the variable
        """
        constr_evals = Array{Dict}(undef, nvars)
        min_evals = Array{Real}(undef, nvars)
        max_evals = Array{Real}(undef, nvars)
        for v in 1:nvars
            var = Variable(m, v)
            lb = ceil(Int, getlowerbound(var))
            ub = floor(Int, getupperbound(var))
            if !isassigned(var_parts, v)
                constr_evals[v] = Dict(j => 0 for j in lb:ub)
                min_evals[v] = 0
                max_evals[v] = 0
            else
                constr_evals[v] = Dict()
                min_eval = Inf
                max_eval = -Inf
                for j in lb:ub
                    val = eval_var(var_parts[v], j)
                    min_eval = min(val, min_eval)
                    max_eval = max(val, max_eval)
                    constr_evals[v][j] = val
                end
                min_evals[v] = min_eval
                max_evals[v] = max_eval
            end
        end
        """
        evals[i] = SeparableFunctionEvaluation(var_parts, function_parts, constant, constr_evals, min_evals, max_evals)

    end

    return evals
end

max_stars_repo_name: ctjandra/ddopt-ecp

max_issues_repo_name: ctjandra/ddopt-ecp

max_forks_repo_name: ctjandra/ddopt-ecp


text:
"""
    chamber(dim=100.0)

Construct a high vacuum chamber to act as the outer-most Region.
"""
chamber(dim = 100.0) = #
    Region(
        RectangularShape([-dim, -dim, -dim], 2.0 * [dim, dim, dim]),
        parse(Material, "H", density = 5.0e-11),
        nothing,
        "Chamber",
        0,
    )

"""
    gun(::Type{T}, energy::Float64, width::Float64=1.0e-7, initial::Position=Position(0.0,0.0,-10.0), direction=Position(0.0,0.0,1.0)::T where {T <: Particle}

A helper to construct the initial `Particle` in a randomized Gaussian distribution.
"""
function gun(
    ::Type{T},
    energy::Float64,
    width::Float64 = 1.0e-7,
    initial::Position = Position(0.0, 0.0, -10.0),
    direction = Position(0.0, 0.0, 1.0),
)::T where {T<:Particle}
    r, th = sqrt(-2.0 * log(rand())) * width, 2.0π * rand()
    st = initial .+ Position(r * cos(th), r * sin(th), 0.0)
    return T(st .- direction, st, energy)
end

"""
    bulk(mat::Material)

Construct a bulk homogeneous sample at the origin.
"""
function bulk(mat::Material)
    c = chamber()
    Region(RectangularShape([-0.1, -0.1, 0.0], [0.2, 0.2, 0.2]), mat, c, "Bulk homogeneous")
    return c
end

"""
    particle(mat::Material, radius::Float64, substrate::Union{Nothing,Material} = nothing)

Construct a spherical particle at the origin with an optional bulk substrate.
"""
function particle(
    mat::Material,
    radius::Float64,
    substrate::Union{Nothing,Material} = nothing,
)
    c = chamber()
    Region(SphericalShape([0.0, 0.0, -radius], radius), mat, c, "Particle")
    if !isnothing(substrate)
        Region(
            RectangularShape([-0.1, -0.1, 0.0], [0.2, 0.2, 0.2]),
            substrate,
            c,
            "Substrate",
        )
    end
    return c
end

"""
    coated_particle(mat::Material, radius::Float64, coating::Material, thickness::Float64, substrate::Union{Nothing,Material} = nothing)

Construct a coated particle on an optional substrate.

This model is a good example of how more complex models are constructed.  Use `dump(..)` to display the structure.  You'll notice that
the chamber serves as the root `Region`.  The `coating` and `substrate` are in the chamber (children of the chamber `Region`).  The
`particle` is a child of the `coating` `Region` because the particle is fully enclosed by the coating.  An electron inside of the coating will
enter the particle and leave the coating as soon as it enters the volume representing the particle.  The electron only appears to be
within the child-most region at any point in space.  So a typical trajectory might start in the chamber, enter the coating, traverse
the thickness of the coating and then enter the particle.  It may eventually leave the particle and reenter the coating, exit the coating
and reenter the chamber and finally come to rest in the substrate.
"""
function coated_particle(
    mat::Material,
    radius::Float64,
    coating::Material,
    thickness::Float64,
    substrate::Union{Nothing,Material} = nothing,
)
    c = chamber()
    cr = Region(
        SphericalShape([0.0, 0.0, -(radius + thickness)], radius + thickness),
        coating,
        c,
        "Coating",
    )
    Region(SphericalShape([0.0, 0.0, -(radius + thickness)], radius), mat, cr, "Particle")
    if !isnothing(substrate)
        Region(
            RectangularShape([-0.1, -0.1, 0.0], [0.2, 0.2, 0.2]),
            substrate,
            c,
            "Substrate",
        )
    end
    return c
end

"""
    thin_film(prs::Pair{Material, Float64}...; substrate::Union{Nothing,Material} = nothing)

Construct sample consisting of one or more thin films on an optional bulk substrate.
"""
function thin_film(
    prs::Pair{Material,Float64}...;
    substrate::Union{Nothing,Material} = nothing,
)
    c = chamber()
    t = 0.0
    for (i, (mat, thick)) in enumerate(prs)
        Region(RectangularShape([-0.1, -0.1, t], [0.2, 0.2, thick]), mat, c, "Layer[$i]")
        t += thick
    end
    if !isnothing(substrate)
        Region(
            RectangularShape([-0.1, -0.1, t], [0.2, 0.2, 0.2 - t]),
            substrate,
            c,
            "Substrate",
        )
    end
    return c
end

"""
    allmaterials(reg::Region)

Generates a list of all the unique materials in a sample Region.
"""
function allmaterials(reg::Region)
    res = [reg.material]
    for ch in reg.children
        append!(res, allmaterials(ch))
    end
    return unique(res)
end

"""
    colorize(reg::Region)::Dict{Material, Color}

Generate a `Dict{Material, Color}` for all the `Materials` in the specified `Region`.
Designed for distinctive but not necessarily attractive colors.
"""
function colorize(reg::Region)::Dict{Material,Color}
    mats = allmaterials(reg)
    colors = distinguishable_colors(
        length(mats) + 2,
        [RGB(0.12, 0.14, 0.47), RGB(0.42, 0.63, 0.85), RGB(0.9, 0.9, 0.9)],
        transform = deuteranopic,
    )[3:end]
    return Dict(mat => col for (mat, col) in zip(mats, colors))
end

"""
    sample(ch::Region)

Extracts the sample portion from within the chamber.
"""
sample(ch::Region)::Vector{Region} = ch.children

function Base.dump(reg::Region, indent = 0)
    print("$(" → "^indent)$reg\n")
    for ch in reg.children
        dump(ch, indent + 1)
    end
end


text:
# Convenience function for rearranging contexts

# Create a new context containing the given contexts stacked horizontally.
#
# Args:
#  x0: X-position of the new root context
#  y0: Y-position of the new root context
#  height: Height of the root context.
#  aligned_contexts: One or more canvases accompanied with a vertical alignment
#                    specifier, giving the vertical positioning of the context.
#
function hstack(x0, y0, height, aligned_contexts::(@compat Tuple{Context, VAlignment})...)
    if isempty(aligned_contexts)
        return context(x0, y0, 0, height)
    end

    widths = [aligned_context[1].box.a[1] for aligned_context in aligned_contexts]
    width = sum(widths)
    total_width_units = sum_component(Length{:w, Float64}, width)

    if total_width_units > 0.0
        width -= total_width_units*w
        width += 1w
    end

    height = y_measure(height)

    root = context(x0, y0, width, height)
    x = 0w
    for (ctx, aln) in aligned_contexts
        ctx = copy(ctx)

        w_component = sum_component(Length{:w, Float64}, ctx.box.a[1])
        box_w = ctx.box.a[1]
        if w_component != 0.0
            box_w = scale_component(Length{:w, Float64},
                                    w_component / total_width_units,
                                    ctx.box.a[1])
        end

        y = ctx.box.x0[2]
        if aln == vtop
            y = 0h
        elseif aln == vcenter
            y = (height / 2) - (ctx.box.a[2] / 2)
        elseif aln == vbottom
            y = height - ctx.box.a[2]
        end

        ctx.box = BoundingBox((x, y), (box_w, ctx.box.a[2]))
        root = compose!(root, ctx)
        x += ctx.box.a[1]
    end

    return root
end

hstack() = context()

# Create a new context containing the given contexts stacked horizontally.
#
# This is the simple version of hstack. The root context will be placed on 0cx,
# 0cy, and its height will be the maximum of the contexts it contains. All
# contexts will be centered vertically.
#
function hstack(contexts::Context...; x0::MeasureOrNumber=0,
                y0::MeasureOrNumber=0, height=0)
    if height == 0
        height = maximum([context.box.a[2] for context in contexts])
    end
    return hstack(x0, y0, height, [(context, vcenter) for context in contexts]...)
end

# Create a new context containing the given contexts stacked vertically.
#
# Args:
#  x0: X-position of the new root context
#  y0: Y-position of the new root context
#  width: Height of the root context.
#  aligned_contexts: One or more canvases accompanied with a horizontal alignment
#                    specifier, giving the horizontal positioning of the context.
#
function vstack(x0, y0, width, aligned_contexts::(@compat Tuple{Context, HAlignment})...)

    if isempty(aligned_contexts)
        return context(x0, y0, width, 0)
    end

    heights = [aligned_context[1].box.a[2] for aligned_context in aligned_contexts]
    height = sum(heights)
    total_height_units = sum_component(Length{:h, Float64}, height)

    if total_height_units > 0.0
        height -= total_height_units*h
        height += 1h
    end

    width = x_measure(width)

    root = context(x0, y0, width, height)
    y = 0h
    for (ctx, aln) in aligned_contexts
        ctx = copy(ctx)

        h_component = sum_component(Length{:h, Float64}, ctx.box.a[2])
        box_h = ctx.box.a[2]
        if h_component != 0.0
            box_h = scale_component(Length{:h, Float64},
                                    h_component / total_height_units,
                                    ctx.box.a[2])
        end

        x = ctx.box.x0[1]
        if aln == hleft
            x = 0w
        elseif aln == hcenter
            x = (width / 2) - (ctx.box.a[1] / 2)
        elseif aln == hright
            x = width - ctx.box.a[1]
        end

        ctx.box = BoundingBox((x, y), (ctx.box.a[1], box_h))
        root = compose!(root, ctx)
        y += ctx.box.a[2]
    end

    return root
end

vstack() = context()

# Create a new context containing the given contexts stacked horizontally.
#
# The simple version of vstack. The root context will be placed on 0cx, 0cy, and
# its width will be the maximum of the contexts it contains. All contexts will
# be centered horizontally..
#
function vstack(contexts::Context...; x0::MeasureOrNumber=0,
                y0::MeasureOrNumber=0, width::MeasureOrNumber=0)
    if width == 0
        width = maximum([context.box.a[1] for context in contexts])
    end
    return vstack(x0, y0, width, [(context, hcenter) for context in contexts]...)
end


text:
using Revise
using lipm

init_position = [0.0, 0.0, 0.0]
goal_position = [5.0, 0.0, 0.0]
X = move_to_position(init_position; goal_position=goal_position)
animate_walking_trajectory(X)


text:
module ML
abstract Regressor
abstract Classifier

include("classifiers/linear_model.jl")
# package code goes here

end # module


text:
const IniType = Dict{String,Dict{String,Any}}
export IniType

function parseini(fname::String)::IniType
    initxt = IniType();
    fid = open(fname)
    blockname = "default"
    seekstart(fid)
    lines = eachline(fid)
    lastkey = ""
    for line in lines
        # skip comments and newlines
        m = match(r"([^#]*)",line);
        line  = strip(chomp(m.captures[1]));
        if isempty(line)
            continue
        end
        # parse blockname
        m = match(r"^\s*\[\s*([^\]]+)\s*\]$", line)
        if (m != nothing)
            blockname = m.captures[1]
            continue
        end
        # parse key/value
        m = match(r"^\s*([^=]*\w)\s*=\s*(.*)\s*$", line)
        if (m != nothing) #Found a key
            lastkey = m.captures[1]
            if haskey(initxt,blockname)
                initxt[blockname][lastkey] = m.captures[2];
            else
                initxt[blockname] = Dict(lastkey => m.captures[2]);
            end
        else #Not a key and not a comment append to last known block and key
            initxt[blockname][lastkey] = string(initxt[blockname][lastkey],line)
        end
    end
    close(fid);
    #eval loop
    mblock=[];mkey=[]
    try
        foreach(keys(initxt)) do block
            mblock = block
            foreach(keys(initxt[block])) do key
                mkey = key
                initxt[block][key] = eval(parse(initxt[block][key]))
            end
        end
    catch e
        error("Error encountered parsing [$(mblock)][$mkey] with\n val: \n $(initxt[mblock][mkey])")
    end
    initxt
end
export parseini

writeln(fid,line) = begin
    isempty(line) && (line = "\n")
    line[end] != '\n' && (line = string(line,"\n"))
    write(fid,line)
end

function saveini{T<:Any}(fname::String,D::Dict{String,Dict{String,T}})
    fid = open(fname,"w+") do fid
        foreach(keys(D)) do block
            block = strip(block)
            writeln(fid,"\n[$block]")
            foreach(keys(D[block])) do key
                key = strip(key)
                writeln(fid,"$key =  $(print_var(D[block][key]))")
            end
        end
    end
    nothing
end
export saveini

function setvarini(fname::String,section::String,varname::String,var)
    section = strip(section)
    varname= strip(varname)
    lines = try
        open(fid->collect(eachline(fid)),fname)
    catch
        info("File not found: creating new file $fname")
        open(fname,"w") do fid
            writeln(fid,"\n[$section]")
            writeln(fid,"$varname = $(print_var(var))")
        end
        return
    end
    S = parseini_structure(lines)
    if !(section in keys(S))
        info("Section [$section] not found in $fname creating new ")
        open(fname,"w") do fid
            writeln(fid,"\n[$section]")
            writeln(fid,"$varname = $(print_var(var))")
            foreach(line->writeln(fid,line),lines)
        end
        return
    end
    if varname in keys(S[section].children)
        info("Variable found: replacing $varname = ")
        insert_line = S[section][varname].start_line-1
        restart_line = S[section][varname].end_line+1
    else
        info("Variable not found: creating $varname = ")
        insert_line = S[section].start_line
        restart_line = S[section].start_line+1
    end
    open(fname,"w") do fid
        for i=1:insert_line writeln(fid,lines[i]); end
        writeln(fid,"$varname = $(print_var(var))")
        for i=restart_line:length(lines) writeln(fid,lines[i]); end
    end
end
export setvarini

print_var(S::String) = string("\"",replace(S,"\\","\\\\"),"\"")
print_var(S::Any) = begin
    res = sprint(print,S)
    for typ in (:Any,:Int32,:Int64,:Float64,:Float32)
        res = replace(res,"$(typ)[","[")
        res = replace(res,",$(typ)[",",[")
    end
    res = replace(res,"],[","],\n\t\t[")
    res
end

print_var{T <: Real}(M::Matrix{T}) = begin
    M = Matrix{Float64}(M)
    res = sprint(print,M)
    res = replace(res,";",";\n\t\t")
end

using StaticArrays
print_var{N1,N2,T <: Real}(M::SMatrix{N1,N2,T}) = begin
    M = Matrix{Float64}(M)
    res = sprint(print,M)
    res = replace(res,";",";\n\t\t")
end

print_var{T <: Real}(VV::Vector{Vector{T}}) = begin
    res = sprint(print,VV)
    res = replace(res,"Array{$T,1}","")
    res = replace(res,"],[","],\n\t\t[")
    res = replace(res,"[[","[\n\t\t[")
end

mutable struct iniNodeInfo
    typ::Symbol
    start_line::Integer
    end_line::Integer
    children
    iniNodeInfo(typ,sl,el) = new(typ,sl,el,Dict{String,iniNodeInfo}())
end
import Base: getindex,setindex!
getindex(ini::iniNodeInfo,a) = ini.children[a]
setindex!(ini::iniNodeInfo,val,key) = setindex!(ini.children,val,key)

function parseini_structure(fname::String)
    open(fname) do fid
        parseini_structure(collect(eachline(fid)))
    end
end
function parseini_structure(lines::Vector{String})
    S = Dict{String,iniNodeInfo}();
    blockname = "default"
    S[blockname] = iniNodeInfo(:block,1,0)
    lastkey = ""
    for idx=1:length(lines)
        line = lines[idx]
        # skip comments and newlines
        m = match(r"([^#]*)",line);
        line  = strip(chomp(m.captures[1]));
        if isempty(line)
            continue
        end
        # parse blockname
        m = match(r"^\s*\[\s*([^\]]+)\s*\]$", line)
        if (m != nothing)
            blockname = m.captures[1]
            S[blockname] = iniNodeInfo(:block,idx,idx)
            continue
        end
        S[blockname].end_line += 1
        # parse key/value
        m = match(r"^\s*([^=]*\w)\s*=\s*(.*)\s*$", line)
        if (m != nothing) #Found a key
            lastkey = m.captures[1]
            S[blockname][lastkey] = iniNodeInfo(:key,idx,idx)
        else #Not a key and not a comment append to last known block and key
            S[blockname][lastkey].end_line += 1
        end
    end
    S
end
nothing


text:
module ModularIndices

using Base: tail
import Base.getindex
export Mod

include("TupleVector.jl")

const IndexArrayTypes = Union{AbstractRange{Int}, AbstractVector{Int}, TupleVector}

"""
    Mod(idx)

Construct a modular (periodic) index.

# Examples
```jldoctest
julia> A = 1:3
1:3

julia> A[Mod(4)]
1

julia> A[Mod(2:4)]
3-element Array{Int64,1}:
 2
 3
 1

```

"""
struct Mod{S <: Union{IndexArrayTypes, Int}}
    ind::S
end

# Allow non-allocating construction
Mod(i₁::Int, i₂::Int, iₓ::Int...) = Mod(TupleVector((i₁, i₂, iₓ...)))

# The `mod_range` function is modified from https://github.com/JuliaLang/julia/pull/32628
# This does the actual modular arithmetic.
@inline mod_range(i::Int, r::Base.OneTo) = mod1(i, last(r))
@inline mod_range(i::Int, r::AbstractUnitRange) = mod(i-first(r), length(r)) + first(r)
@inline mod_range(i::Int, r::StepRange) = abs(r.step)==1 ? mod(i-minimum(r), length(r)) + minimum(r) :
    throw(ArgumentError("step must be +1 or -1"))

@inline mod_range(i::IndexArrayTypes, r) = TupleVector(ntuple(j -> mod_range(i[j], r), length(i)))

# By construction, `Mod` indices are be in bounds
@inline Base.checkindex(::Type{Bool}, inds::AbstractUnitRange, index::Mod) = true

# The key bit: peel off `Mod`'s and compute the mod given the axis information (in `inds`)
# For example, A[Mod(5)] == A[mod_range(5, axes(A, 1))]
@inline function Base.to_indices(A, inds, I::Tuple{Mod, Vararg{Any}})
    return to_indices(A, inds, (mod_range(I[1].ind, inds[1]), tail(I)...))
end

end # module


text:
# Representations of distributions suitable for Stein discrepancy calculations
module SteinDistributions

export
# Abstract types
SteinDistribution,
SteinPosterior,
# Specific distributions
SteinDiscrete,
SteinDiscreteUniform,
SteinGMM,
SteinGMMPosterior,
SteinGaussian,
SteinLogisticRegressionPosterior,
SteinLogisticRegressionGaussianPrior,
SteinMultivariateStudentTRegressionPosterior,
SteinMultivariateStudentTRegressionGaussianPrior,
SteinMultivariateStudentTRegressionPseudoHuberPrior,
SteinHuberLossRegressionPosterior,
SteinHuberLossRegressionGaussianPrior,
SteinProbitRegression,
SteinProbitRegressionGaussianPrior,
SteinMRF,
SteinMultinomial,
SteinOctahedron,
SteinPotts,
SteinScaleLocationStudentT,
SteinUniform,
SteinBanana,
SteinHierarchericalPoisson,
SteinSquaredFourierSumDensity,
# Common functions operating on distributions
# CDF of a distribution
cdf,
# Get Stein factors
getC1,
getC2,
getC3,
# Lower bound on range of coordinate
supportlowerbound,
# Upper bound on range of coordinate
supportupperbound,
# Number of dimensions of target variable
numdimensions,
# get number of samples when distribution is posterior of data
numdatapoints,
# the log prior for posterior distributions
logprior,
# the likelihood [without a prior for posterior distributions]
loglikelihood,
# Log density [will include prior for posterior distributions]
logdensity,
# Gradient of the prior
gradlogprior,
# Gradient of the density
graddensity,
# Gradient of the log density
gradlogdensity,
# Gradient of the log likelihood
gradloglikelihood,
# Random samples drawn from distribution
rand,
# random GMM samples
randgmm,
# random SteinBanana samples
randbanana,
# random procedure for SteinHierarchericalPoisson
rungibbs,
# evaluating joint and conditional probability mass functions for
# discrete distributions
jointdistribution,
condlogodds,
conddistribution

# Include abstract types first
include("SteinDistribution.jl")
include("SteinPosterior.jl")
# Include specific distributions
include("SteinDiscrete.jl")
include("SteinDiscreteUniform.jl")
include("SteinGMM.jl")
include("SteinGMMPosterior.jl")
include("SteinGaussian.jl")
include("SteinLogisticRegressionPosterior.jl")
include("SteinLogisticRegressionGaussianPrior.jl")
include("SteinMultivariateStudentTRegressionPosterior.jl")
include("SteinMultivariateStudentTRegressionGaussianPrior.jl")
include("SteinMultivariateStudentTRegressionPseudoHuberPrior.jl")
include("SteinHuberLossRegressionPosterior.jl")
include("SteinHuberLossRegressionGaussianPrior.jl")
include("SteinProbitRegression.jl")
include("SteinProbitRegressionGaussianPrior.jl")
include("SteinMRF.jl")
include("SteinMultinomial.jl")
include("SteinOctahedron.jl")
include("SteinPotts.jl")
include("SteinScaleLocationStudentT.jl")
include("SteinUniform.jl")
include("SteinBanana.jl")
include("SteinHierarchericalPoisson.jl")
include("SteinSquaredFourierSumDensity.jl")
end


text:
using Distributed
using Plots

workers = 5

if nprocs() <= workers
    addprocs(workers + 1 - nprocs())
end

@everywhere include("models/Dicke.jl")
@everywhere include("modules/ClassicalDynamics.jl")

""" Calculates Poincaré sections  with Lyapunov exponents for various energies
    Parallel calculation, takes usually days to finish
"""
function DickeEnergies()
    savePath = "d:\\results\\Dicke"

    @sync @distributed for energy = -1:0.1:10
        parameters = [1.0, 1.0, 1.0, 1.0]
        dimension = 101

        sectionLyapunov, trajectories = SolveEnergy(energy, parameters, dimension, savePath=savePath)

        # Save results
        open(savePath * "_PS_E=$(energy)_$parameters.txt", "w") do io
            println(io, sectionLyapunov)
        end
    end
end

savePath = "d:\\results\\Dicke"
parameters = [1.0, 1.0, 1.0, 1.0]
dimension = 101

c = Channel()
x = @async put!(remotecall_fetch(SolveEnergy, 2, 0, parameters, dimension, savePath="d:\\results\\Dicke"))
global i = 0.0
while !isready(c)
    global i
    i += 0.1
end
println(x)

max_stars_repo_name: PavelStransky/ClassicalDynamics

max_issues_repo_name: PavelStransky/ClassicalDynamics

max_forks_repo_name: PavelStransky/ClassicalDynamics


text:
"""
    $(TYPEDEF)

An image file directory is a sorted collection of the tags representing this
plane in the TIFF file. They behave like dictionaries, so given an IFD called
`ifd`, we can add new tags as follows:

```jldoctest; setup = :(ifd = TiffImages.IFD(UInt32))
julia> ifd[TiffImages.IMAGEDESCRIPTION] = "Some details";

julia> ifd[TiffImages.IMAGEWIDTH] = 512;

julia> ifd
IFD, with tags:
	Tag(IMAGEWIDTH, 512)
	Tag(IMAGEDESCRIPTION, "Some details")
```
"""
struct IFD{O <: Unsigned}
    tags::DefaultDict{UInt16, Vector{Tag}, DataType}
end

IFD(::Type{O}) where {O <: Unsigned} = IFD{O}(DefaultDict{UInt16, Vector{Tag}}(Vector{Tag}))
IFD(::Type{O}, tags) where {O <: Unsigned} = IFD{O}(tags)

"""
A wrapper to force getindex to return the underlying array instead of only the
first element. Usually the first element is sufficient, but sometimes access to
the array is needed (to add duplicate entries or access them).

```jldoctest; setup = :(ifd = TiffImages.IFD(UInt32))
julia> using TiffImages: Iterable

julia> ifd[TiffImages.IMAGEDESCRIPTION] = "test"
"test"

julia> ifd[Iterable(TiffImages.IMAGEDESCRIPTION)] # since wrapped with Iterable, returns array
1-element Vector{TiffImages.Tag}:
 Tag(IMAGEDESCRIPTION, "test")

julia> ifd[Iterable(TiffImages.IMAGEDESCRIPTION)] = "test2" # since wrapped with Iterable, it appends
"test2"

julia> ifd
IFD, with tags:
	Tag(IMAGEDESCRIPTION, "test")
	Tag(IMAGEDESCRIPTION, "test2")

```
"""
struct Iterable{T}
    key::T
end

Base.length(ifd::IFD) = sum(map(length, values(ifd.tags)))
Base.keys(ifd::IFD) = keys(ifd.tags)
Base.iterate(ifd::IFD) = iterate(ifd.tags)
Base.iterate(ifd::IFD, n::Int) = iterate(ifd.tags, n)

Base.getindex(ifd::IFD, key::Iterable{TiffTag}) = getindex(ifd, Iterable(UInt16(key.key)))
Base.getindex(ifd::IFD, key::Iterable{UInt16}) = getindex(ifd.tags, key.key)
Base.getindex(ifd::IFD, key::TiffTag) = getindex(ifd, UInt16(key))
Base.getindex(ifd::IFD, key::UInt16) = first(getindex(ifd.tags, key))

Base.in(key::TiffTag, v::IFD) = in(UInt16(key), v)
Base.in(key::UInt16, v::IFD) = in(key, keys(v))
Base.delete!(ifd::IFD, key::TiffTag) = delete!(ifd, UInt16(key))
Base.delete!(ifd::IFD, key::UInt16) = delete!(ifd.tags, key)

Base.similar(::IFD{O}) where {O <: Unsigned} = IFD(O)
Base.merge(ifd::IFD{O}, other::IFD{O}) where {O <: Unsigned} = IFD(O, DefaultDict(Vector{Int}, merge(ifd.tags, other.tags)))

Base.setindex!(ifd::IFD, value::Tag, key::UInt16) = setindex!(ifd.tags, [value], key)
Base.setindex!(ifd::IFD, value::Tag, key::TiffTag) = setindex!(ifd, value, UInt16(key))

Base.setindex!(ifd::IFD, value, key::TiffTag) = setindex!(ifd, value, UInt16(key))
Base.setindex!(ifd::IFD, value, key::UInt16) = setindex!(ifd, Tag(key, value), key)

Base.setindex!(ifd::IFD, value, key::Iterable{TiffTag}) = setindex!(ifd, value, Iterable(UInt16(key.key)))
Base.setindex!(ifd::IFD, value, key::Iterable{UInt16}) = setindex!(ifd, Tag(key.key, value), key)
Base.setindex!(ifd::IFD, value::Tag, key::Iterable{UInt16}) = push!(ifd.tags[key.key], value)

"""
    $SIGNATURES

Checks if the data in this IFD is contiguous on disk. Striped data can be read
faster as one contiguous chunk if possible.
"""
function iscontiguous(ifd::IFD)
    if !(ROWSPERSTRIP in ifd) || nrows(ifd) == ifd[ROWSPERSTRIP].data
        return true
    else
        return all(diff(ifd[STRIPOFFSETS].data) .== ifd[STRIPBYTECOUNTS].data[1:end-1])
    end
end

function load!(tf::TiffFile, ifd::IFD)
    for key in sort(collect(keys(ifd)))
        tags = ifd[Iterable(key)]
        for (idx, tag) in enumerate(tags)
            tags[idx] = load(tf, tag)
        end
    end
end

function Base.show(io::IO, ifd::IFD)
    print(io, "IFD, with tags: ")
    for key in sort(collect(keys(ifd)))
        tags = ifd[Iterable(key)]
        for tag in tags
            print(io, "\n\t", tag)
        end
    end
end

function Base.read(tf::TiffFile{O}, ::Type{IFD}) where O <: Unsigned
    # Regular TIFF's use 16bits instead of 32 bits for entry data
    N = O == UInt32 ? read(tf, UInt16) : read(tf, O)

    entries = IFD(O)

    for i in 1:N
        tag = read(tf, Tag)
        push!(entries[Iterable(tag.tag)], tag)
    end

    next_ifd = Int(read(tf, O))
    entries, next_ifd
end

function Base.iterate(file::TiffFile{O}) where {O}
    seek(file.io, file.first_offset)
    iterate(file, (read(file, IFD)))
end

"""
    iterate(file, state) -> IFD, Int

Advances the iterator to the next IFD.

**Output**
- `Vector{Int}`: Offsets within file for all strips corresponding to the current
   IFD
- `Int`: Offset of the next IFD
"""
function Base.iterate(file::TiffFile, state::Tuple{Union{IFD{O}, Nothing}, Int}) where {O}
    curr_ifd, next_ifd_offset = state
    # if current element doesn't exist, exit
    (curr_ifd == nothing) && return nothing
    (next_ifd_offset <= 0) && return (curr_ifd, (nothing, 0))

    seek(file.io, next_ifd_offset)
    next_ifd, next_ifd_offset = read(file, IFD)

    return (curr_ifd, (next_ifd, next_ifd_offset))
end

function Base.read!(target::AbstractArray{T, N}, tf::TiffFile, ifd::IFD) where {T, N}
    strip_offsets = ifd[STRIPOFFSETS].data

    if PLANARCONFIG in ifd
        planarconfig = ifd[PLANARCONFIG].data
        (planarconfig != 1) && error("Images with data stored in planar format not yet supported")
    end

    rows = nrows(ifd)
    cols = ncols(ifd)
    compression = COMPRESSION_NONE
    try
        compression = CompressionType(ifd[COMPRESSION].data)
    catch
    end

    if !iscontiguous(ifd) || compression != COMPRESSION_NONE
        rowsperstrip = rows
        (ROWSPERSTRIP in ifd) && (rowsperstrip = ifd[ROWSPERSTRIP].data)
        nstrips = ceil(Int, rows / rowsperstrip)

        strip_nbytes = ifd[STRIPBYTECOUNTS].data

        if compression != COMPRESSION_NONE
            # strip_nbytes is the number of bytes pre-inflation so we need to
            # calculate the expected size once decompressed and update the values
            strip_nbytes = fill(rowsperstrip*cols*sizeof(T), length(strip_nbytes)::Int)
            strip_nbytes[end] = (rows - (rowsperstrip * (nstrips-1))) * cols * sizeof(T)
        end

        startbyte = 1
        for i in 1:nstrips
            seek(tf, strip_offsets[i]::Core.BuiltinInts)
            nbytes = Int(strip_nbytes[i]::Core.BuiltinInts / sizeof(T))
            read!(tf, view(target, startbyte:(startbyte+nbytes-1)), compression)
            startbyte += nbytes
        end
    else
        seek(tf, strip_offsets[1]::Core.BuiltinInts)
        read!(tf, target, compression)
    end
end

function Base.write(tf::TiffFile{O}, ifd::IFD{O}) where {O <: Unsigned}
    N = length(ifd)
    O == UInt32 ? write(tf, UInt16(N)) : write(tf, UInt64(N))

    # keep track of which tags are too large to fit in the IFD slot and need a
    # remote location for their data
    remotedata = Vector{Pair{Tag, Vector{Int}}}()
    sorted_keys = sort(collect(keys(ifd)))
    for k in sorted_keys
        tags = ifd[Iterable(k)]
        for tag in tags
            pos = position(tf.io)
            if !write(tf, tag)
                push!(remotedata, tag => [pos])
            end
        end
    end

    # end position, write a zero by default, but this should be updated if any
    # more IFDs are written
    ifd_end_pos = position(tf.io)
    write(tf, O(0))

    for (tag, poses) in remotedata
        tag = tag::Tag
        data_pos = position(tf.io)
        data = tag.data
        # add NUL terminator to the end of Strings that don't have it already
        if eltype(tag) === String
            data = data::SubString{String}
            if !endswith(data, '\0')
                data *= '\0'
            end
            write(tf, data)  # compile-time dispatch
        else
            write(tf, data)  # run-time dispatch
        end
        push!(poses, data_pos)
    end

    for (tag, poses) in remotedata
        tag = tag::Tag
        orig_pos, data_pos = poses
        seek(tf, orig_pos)
        write(tf, tag, data_pos)
    end

    seek(tf, ifd_end_pos)

    return ifd_end_pos
end


text:
import Nemo.setcoeff!, Nemo.lift, Hecke.lift, Nemo.rem
export psi_lower, psi_upper, show_psi

#function setcoeff!(g::fmpz_mod_rel_series, i::Int64, a::Nemo.Generic.Res{Nemo.fmpz})
#  setcoeff!(g, i, lift(a))
#end

function bernstein(h::Int, it::Any, Q = FlintQQ, cl = ceil, a::Int = 776)
  #use 771 and cl = floor to get decent upper bounds
  # more on the choice of 776 and 771 in Dan's paper

  #println("in bernstein with a=$a and cl(0.5) = $(cl(0.5))")
  R,t = PowerSeriesRing(Q, a*h+1, "t", model = :capped_absolute)

  #implements https://cr.yp.to/papers/psi.pdf
  # for smoothness for ideals, replace next_prime by the list of the norms of the prime
  # ideals
  # the sums of the coefficients of exp(g) are bounds for psi

  res = iterate(it)
  p, st = res

  #st = start(it)
  #p, st = next(it, st)
  g = R(0)
  tp = R(0)
  lpp = Int(cl(Float64(log(p))/log(2)*a))

  function do_single!(g::SeriesElem, pp::Int, np::Int)
    i = pp
    nu = Q(np)*Q(pp)
    while i <= a*h
      A = coeff(g, i)
      A += divexact(nu, Q(i))
      setcoeff!(g, i, lift(A))
      i += pp
    end
  end

  done = false

  while true
    pp = lpp
    np = 0
    while pp == lpp && res !== nothing #!done(it, st)
      np += 1
      res = iterate(it, st)
      if res === nothing
        break
      else
        p, st = res
      end
      lpp = Int(cl(Float64(log(p))/log(2)*a))

      if iterate(it, st) === nothing
        done = true
      else
        done = false
      end

      if done
        break
      end
    end

    if done && pp == lpp
      np += 1
    end

    do_single!(g, pp, np)

    if done
      if pp != lpp
        do_single!(g, lpp, 1)
      end
      return g
    end
  end
end

function _exp(a::fmpz_mod_abs_series)
  R = base_ring(parent(a))
  R = ResidueRing(FlintZZ, Int(modulus(R)), cached = false)
  Rx,x = PolynomialRing(R, cached = false)
  A = Rx()
  for i=0:length(a)
    setcoeff!(A, i, lift(coeff(a, i)))
  end
  E = Rx()
  ccall((:nmod_poly_exp_series, libflint), Nothing, (Ref{nmod_poly}, Ref{nmod_poly}, Int64), E, A, length(a))
  r = parent(a)()
  for i=0:Nemo.length(E)-1
    setcoeff!(r, i, lift(coeff(E, i)))
  end
  return r
end

function lift(R::FmpzAbsSeriesRing, f::fmpz_mod_abs_series)
  r = R()
  for i=0:length(f)-1
    setcoeff!(r, i, lift(coeff(f, i)))
  end
  return r
end

function _psi_lower(N::fmpz, pr, a::Int=776, cl = ceil)
  p = fmpz(next_prime(2^60))
  n = nbits(N)
#  println("precision of $n")
  f = _exp(bernstein(n, pr, ResidueRing(FlintZZ, p, cached = false), cl, a))
  Rt, t = PowerSeriesRing(FlintZZ, n*a+1, "t", model = :capped_absolute)
  f = lift(Rt, f)
  pp = p
  while pp < N
    p = next_prime(p)
#    println("p: $p, pp: $pp N:$N")
    g = _exp(bernstein(n, pr, ResidueRing(FlintZZ, p, cached = false), cl, a))
    @assert length(g) == length(f)
    for i=0:length(f)
      setcoeff!(f, i, crt(coeff(f, i), pp, lift(coeff(g, i)), p))
    end
    pp *= p
  end
  res = []
  s = 0
  j = 0
  for i=0:n
    while j <= i*a && j < length(f)
      s += coeff(f, j)
      j += 1
    end
    push!(res, s)
    if j >= length(f) break; end
  end
  return res, f  # res[i] <= psi(2^(i-1), B)
end

@doc Markdown.doc"""
    psi_lower(N::Integer, B::Int) -> Array{Int, 1}, fmpz_abs_series
    psi_lower(N::fmpz, B::Int) -> Array{Int, 1}, fmpz_abs_series

Uses Bernstein's ideas: https://cr.yp.to/papers/psi.pdf
to compute lower bounds on the psi function counting smooth numbers.
An array L is returned s.th $\psi(2^{i-1}, B) \ge L_i$ for
$1\le i\le \rceil \log_2(B)\lceil$.
The second return value is Bernstein's power series.
>
The optional other parameter $a$ controls the precision of the result,
it defaults to 776.
"""
function psi_lower(N::fmpz, B::Int, a::Int = 776)
  return _psi_lower(fmpz(N), PrimesSet{Int}(2, B), a, ceil)
end

function psi_lower(N::Integer, B::Int, a::Int = 776)
  return _psi_lower(fmpz(N), PrimesSet{Int}(2, B), a, ceil)
end

@doc Markdown.doc"""
    psi_upper(N::Integer, B::Int) -> Array{Int, 1}, fmpz_abs_series
    psi_upper(N::fmpz, B::Int) -> Array{Int, 1}, fmpz_abs_series

Uses Bernstein's ideas: https://cr.yp.to/papers/psi.pdf
to compute upper bounds on the psi function counting smooth numbers.
An array U is returned s.th $\psi(2^{i-1}, B) \ge U_i$ for
$1\le i\le \rceil \log_2(B)\lceil$.
The second return value is Bernstein's power series.
>
The optional other parameter $a$ controls the precision of the result,
it defaults to 771.
"""
function psi_upper(N::fmpz, B::Int, a::Int=771)
  return _psi_lower(N, PrimesSet{Int}(2, B), a, floor)
end

function psi_upper(N::Integer, B::Int, a::Int=771)
  return _psi_lower(fmpz(N), PrimesSet{Int}(2, B), a, floor)
end

@doc Markdown.doc"""
    show_psi(N::Integer, B::Int)
    show_psi(N::fmpz, B::Int)

Uses \code{psi_lower} and \code{psi_upper} to find intervalls for
$\psi(2^i, B)$ to be in for $0\le i\le \log_2(N)$.
Where $\psi(N, B) = \#\{1\le i\le N | \text{$i$ is $B$-smooth}\}$
"""
function show_psi(N::Integer, B::Union{Int, NfFactorBase})
  gl = psi_lower(N, B)[1]
  gu = psi_upper(N, B)[1]
  l = 0
  u = 0
  for i=1:length(gl)
    if isa(B, Int)
      print("psi(2^$(i-1), $B)")
    else
      print("psi(2^$(i-1), B)")
    end
    l = gl[i]
    u = gu[i]
    if l==u
      println(" == $l")
    else
      println(" in [$l, $u]")
    end
  end
end

function show_psi(N::fmpz, B::Int)
  show_psi(BigInt(N), B)
end

@doc Markdown.doc"""
    psi_lower(N::Integer, B::NfFactorBase) -> Array{Int, 1}, fmpz_abs_series
    psi_lower(N::fmpz, B::NfFactorBase) -> Array{Int, 1}, fmpz_abs_series

    psi_upper(N::Integer, B::NfFactorBase) -> Array{Int, 1}, fmpz_abs_series
    psi_upper(N::fmpz, B::NfFactorBase) -> Array{Int, 1}, fmpz_abs_series

Uses Bernstein's techniques to bound the number of ideals $A$
of norm bounded by $N$ that are smooth over the factor base $B$.
"""
function psi_lower(N::Integer, B::NfFactorBase, a::Int=776)
  lp = sort(fmpz[norm(x) for x=B.ideals])
  return _psi_lower(fmpz(N), lp, a, ceil)
end

function psi_lower(N::fmpz, B::NfFactorBase, a::Int=776)
  lp = sort(fmpz[norm(x) for x=B.ideals])
  return _psi_lower(N, lp, a, ceil)
end

function psi_upper(N::Integer, B::NfFactorBase, a::Int=771)
  lp = sort(fmpz[norm(x) for x=B.ideals])
  return _psi_lower(fmpz(N), lp, a, floor)
end

function psi_upper(N::fmpz, B::NfFactorBase, a::Int=771)
  lp = sort(fmpz[norm(x) for x=B.ideals])
  return _psi_lower(N, lp, a, floor)
end

#=
test:

julia> sp = PrimesSet(2, 100);
julia> fb = []; for x=sp push!(fb, fmpz(x)); end;
julia> fb = FactorBase(fb)
julia> length(find(x->issmooth(fb, fmpz(x)), 1:256))
julia> @assert psi_lower(255, 100)[1][end] == ans

=#


text:
"""
    matB(X, y; fun = mean)
Compute the between covariance matrix ("B") of `X`.
* `X` : X-data (n, p).
* `y` : A vector (n,) defing the class memberships.
"""
matB = function(X, y)
    X = ensure_mat(X)
    y = vec(y)
    z = aggstat(X; group = y, fun = mean)
    B = matcov(z.res, mweights(z.ni))
    (B = B, ct = z.res, lev = z.lev, ni = z.ni)
end

"""
    matW(X, y; fun = mean)
Compute the within covariance matrix ("W") of `X`.
* `X` : X-data (n, p).
* `y` : A vector (n,) defing the class memberships.
"""
matW = function(X, y)
    X = ensure_mat(X)
    y = vec(y)
    ztab = tab(y)
    lev = ztab.keys
    nlev = length(lev)
    ni = collect(values(ztab))
    # Case with y(s) with only 1 obs
    sum(ni .== 1) > 0 ? sigma_1obs = matcov(X) : nothing
    # End
    w = mweights(ni)
    Wi = list(nlev, Matrix{Float64})
    W = zeros(1, 1)
    @inbounds for i in 1:nlev
        if ni[i] == 1
            Wi[i] = sigma_1obs
        else
            s = findall(y .== lev[i])
            Wi[i] = matcov(X[s, :])
        end
        if i == 1
            W = w[i] * Wi[i]
        else
            W = W + w[i] * Wi[i]
            # Alternative: Could give weight=0 to the class(es) with 1 obs
        end
    end
    (W = W, Wi = Wi, lev = lev, ni = ni)
end


text:
using SparseArrays

@i function i_mul!(C::StridedVecOrMat, A::AbstractSparseMatrix, B::StridedVector{T}, α::Number, β::Number) where T
    @safe size(A, 2) == size(B, 1) || throw(DimensionMismatch())
    @safe size(A, 1) == size(C, 1) || throw(DimensionMismatch())
    @safe size(B, 2) == size(C, 2) || throw(DimensionMismatch())
    nzv ← nonzeros(A)
    rv ← rowvals(A)
    if (β != 1, ~)
        @safe error("only β = 1 is supported, got β = $(β).")
    end
    # Here, we close the reversibility check inside the loop to increase performance
    @invcheckoff for k = 1:size(C, 2)
        @inbounds for col = 1:size(A, 2)
            αxj ← zero(T)
            αxj += B[col,k] * α
            for j = SparseArrays.getcolptr(A)[col]:(SparseArrays.getcolptr(A)[col + 1] - 1)
                C[rv[j], k] += nzv[j]*αxj
            end
            αxj -= B[col,k] * α
        end
    end
end

@i function i_dot(r::T, A::SparseMatrixCSC{T},B::SparseMatrixCSC{T}) where {T}
    m ← size(A, 1)
    n ← size(A, 2)
    @invcheckoff branch_keeper ← zeros(Bool, 2*m)
    @safe size(B) == (m,n) || throw(DimensionMismatch("matrices must have the same dimensions"))
    @invcheckoff @inbounds for j = 1:n
        ia1 ← A.colptr[j]
        ib1 ← B.colptr[j]
        ia2 ← A.colptr[j+1]
        ib2 ← B.colptr[j+1]
        ia ← ia1
        ib ← ib1
        @inbounds for i=1:ia2-ia1+ib2-ib1-1
            ra ← A.rowval[ia]
            rb ← B.rowval[ib]
            if (ra == rb, ~)
                r += A.nzval[ia]' * B.nzval[ib]
            end
            ## b move -> true, a move -> false
            branch_keeper[i] ⊻= ia == ia2-1 || (ib != ib2-1 && ra > rb)
            ra → A.rowval[ia]
            rb → B.rowval[ib]
            if (branch_keeper[i], ~)
                INC(ib)
            else
                INC(ia)
            end
        end
        ~@inbounds for i=1:ia2-ia1+ib2-ib1-1
            ## b move -> true, a move -> false
            branch_keeper[i] ⊻= ia == ia2-1 || (ib != ib2-1 && A.rowval[ia] > B.rowval[ib])
            if (branch_keeper[i], ~)
                INC(ib)
            else
                INC(ia)
            end
        end
    end
    @invcheckoff branch_keeper → zeros(Bool, 2*m)
end


text:
using Random

# mod must always be positive

function mod(a, n)
    if (t = a % n) < 0
        n + t
    else
        t
    end
end

#=
a^b (mod n) using the method of repeated squares.

The key here is that every integer can be written as a sum of powers of 2 (binary numbers)
and that includes the exponent. By repeated squaring we get a raised to a power of 2. Also
recall that a^b * a^c = a^(b + c), so rather than adding we multiply since we are dealing
with the exponent.
=#

function powerMod(a, d, n)
    v = 1 # Value
    p = a # Powers of a
    while d > 0
        if isodd(d) # 1 bit in the exponent
           v = mod(v * p, n)
        end
        p = mod(p^2, n) # Next power of two
        d >>>= 1
    end
    v
end

#=
Greatest common divisor, Euclidean version.
=#

function gcd(a, b)
    while b ≠ 0
        a, b = b, mod(a, b)
    end
    a
end

#=
Least common multiple, necessary for Carmichael's 𝝺 function.
=#

lcm(a, b) = abs(a * b) ÷ gcd(a, b)

#=
Witness loop of the Miller-Rabin probabilistic primality test.
=#

function witness(a, n)
    u, t = n - 1, 0
    while iseven(u) # n = u * 2^t + 1
        t += 1   # Increase exponent
        u >>>= 1 # Decrease the multiplier
    end
    x = powerMod(a, u, n)
    for i in 1:t
        y = powerMod(x, 2, n)
        if y == 1 && x ≠ 1 && x ≠ n - 1
            return true
        end
        x = y
    end
    x ≠ 1
end

function isPrime(n, k)
    if n < 2 || (n ≠ 2 && iseven(n)) # 0, 1, and even except for 2 are not prime.
        return false
    elseif n < 4 # 3 is prime
        return true
    end # We must test all others
    for j in 1:k
        a = rand(2:n - 2) # Choose a random witness
        if witness(a, n)
            return false
        end
    end
    true
end

#=
We need a random prime number in [low, high] and for now a 1/4^100 chance of a composite is
good enough.
=#

function randomPrime(low, high)
    guess = 0 # Certainly not prime!
    while !isPrime(guess, 100)
        guess = rand(low:high) # Half will be even, the rest have Pr[prime] ≈ 1/log(N).
    end
    guess
end

#=
A safe prime is the one following a Sophie German prime. If prime(p) and prime(2p + 1) then
2p + 1 is a safe prime.
=#

function safePrime(low, high)
    p = randomPrime(low, high)
    while !isPrime(2 * p + 1,100)
        p = randomPrime(low, high)
    end
    return 2 * p + 1
end

#=
Multiplicative inverse of a (mod n), using Bézout's identity.
=#

function inverse(a, n)
    r, rP = n, a
    t, tP = 0, 1
    while rP ≠ 0
        q = r ÷ rP
        r, rP = rP, r - q * rP
        t, tP = tP, t - q * tP
    end
    if r > 1
        return "no inverse"
    end
    if t < 0
        t + n
    else
        t
    end
end

#=
An RSA key is a triple (e, d, n):
    e is the public exponent
    d is the private exponent
    n is the modulus
=#

function makeKey(bits)
    size = bits ÷ 2
    low  = big"2"^(size - 1) # Assure the primes are each approximately half of the
    high = big"2"^size - 1   # bits in the modulus.
    p = safePrime(low, high)
    q = safePrime(low, high)
    𝝺 = lcm(p - 1, q - 1) # Carmichael 𝝺(n) = lcm(𝝺(p), 𝝺(q)) = lcm(p - 1, q - 1)
    e = 2^16 + 1          # Default public exponent
    while gcd(e, 𝝺) ≠ 1   # Happens only if we are very unlucky
        e = randomPrime(low, high)
    end
    d = inverse(e, 𝝺) # Private key
    n = p * q         # Modulus
    (e, d, n)
end

encrypt(m, e, n) = powerMod(m, e, n)
decrypt(c, d, n) = powerMod(c, d, n)

max_stars_repo_name: darrelllong/RSA-in-Julia

max_issues_repo_name: darrelllong/RSA-in-Julia

max_forks_repo_name: darrelllong/RSA-in-Julia


text:
import FileIO: load, save
import ImageTransformations: imresize
import Dates: now
# import ImageView: imshow # imshow(vcat_img)

function CombineScreenShots(;
    imgs_dir = joinpath(homedir(), "Desktop"),
    logo_dir = joinpath(homedir(), "Documents/Meta/Technique/Website/logo/Likan.Zhan.Weibo.jpeg"),
    outs_dir = joinpath(imgs_dir, string("Combined-", now(), ".jpg"))
    )

    img_list = filter(Base.Fix1(occursin, "Screen Shot"), readdir(imgs_dir, join = true) )
    sort!(img_list)

    function image_resize(img_name)
        old_image = load(img_name);
        resize_ratio = size(old_image, 2) / 2000
        new_size = round.(Int, size(old_image) ./ resize_ratio)
        new_image = imresize(old_image, new_size)
        return new_image
    end

    vcat_img = mapreduce(image_resize, vcat, [img_list; logo_dir])

    oys, oxs = size(vcat_img)
    MaxSize, ScaleFactor = 5, 5
    imgSize = oys * oxs / (ScaleFactor * 2^20) / MaxSize # 1 mebibyte = 2^20 bytes
    (imgSize > 1 ) && (vcat_img =  imresize(vcat_img, ratio = sqrt(1/imgSize)) )

    save(outs_dir, vcat_img)

    rm.(img_list)
end # function


text:
#######################################################################
# An example of creating an Excel charts with gradient fills using
#  XlsxWriter.
#
# Original Python Copyright 2013-2016, John McNamara, jmcnamara@cpan.rg
# https://github.com/jmcnamara/XlsxWriter

using XlsxWriter

function test()

	wb = Workbook("chart_gradient.xlsx")
	ws = add_worksheet!(wb)
	bold = add_format!(wb, Dict("bold"=> 1))

	# Add the worksheet data that the charts will refer to.
	headings = ["Number" "Batch 1" "Batch 2"]
	data = [
		[2 3 4 5 6 7];
		[10 40 50 20 10 50];
		[30 60 70 50 40 30];
	]

	write_row!(ws, "A1", headings, fmt=bold)
	write_column!(ws, "A2", data[1, :])
	write_column!(ws, "B2", data[2, :])
	write_column!(ws, "C2", data[3, :])

	# Create a new column chart.
	chart = add_chart!(wb, Dict("type"=> "column"))

	# Configure the first series, including a gradient.
	add_series!(chart, Dict(
		"name"=>       "=Sheet1!\$B\$1",
		"categories"=> "=Sheet1!\$A\$2:\$A\$7",
		"values"=>     "=Sheet1!\$B\$2:\$B\$7",
		"gradient"=>   Dict("colors"=> ["#963735", "#F1DCDB"])
	))

	# Configure the second series, including a gradient.
	add_series!(chart, Dict(
		"name"=>       "=Sheet1!\$C\$1",
		"categories"=> "=Sheet1!\$A\$2:\$A\$7",
		"values"=>     "=Sheet1!\$C\$2:\$C\$7",
		"gradient"=>   Dict("colors"=> ["#E36C0A", "#FCEADA"])
	))

	# Set a gradient for the plotarea.
	set_plotarea!(chart, Dict(
		"gradient"=> Dict("colors"=> ["#FFEFD1", "#F0EBD5", "#B69F66"])
	))

	# Add some axis labels.
	set_x_axis!(chart, Dict("name"=> "Test number"))
	set_y_axis!(chart, Dict("name"=> "Sample length (mm)"))

	# Turn off the chart legend.
	set_legend!(chart, Dict("none"=> true))

	# Insert the chart into the worksheet.
	insert_chart!(ws, "E2", chart)

	close(wb)
	isfile("chart_gradient.xlsx")
end

test()


text:
using StaticArrays
using OrdinaryDiffEq
using Test

@inbounds @inline function ż(z, p, t)
    A, B, D = p
    p₀, p₂ = z[1:2]
    q₀, q₂ = z[3:4]

    return SVector{4}(
        -A * q₀ - 3 * B / √2 * (q₂^2 - q₀^2) - D * q₀ * (q₀^2 + q₂^2),
        -q₂ * (A + 3 * √2 * B * q₀ + D * (q₀^2 + q₂^2)),
        A * p₀,
        A * p₂
  )
end

condition(u, t, integrator) = u
affect!(integrator) = nothing
cbf(idx) = ContinuousCallback(condition,
    affect!, nothing, save_positions=(false, true), idxs=idx)
z0 = SVector{4}(7.1989885061904335, -0.165912283356219, 0., -3.63534900748947)

tspan=(0.,300.)
prob=ODEProblem(ż, z0, tspan, (A=1, B=0.55, D=0.4), callback=cbf(3))
sol=solve(prob, Vern9(), abstol=1e-14, reltol=1e-14,
    save_everystep=false, save_start=false, save_end=false, maxiters=1e6)

@test length(sol) > 100

prob=ODEProblem(ż, z0, (0,400.), (A=1, B=0.55, D=0.4), callback=cbf(3))
sol=solve(prob, Vern9(), abstol=1e-14, reltol=1e-14, save_everystep=false, save_start=false, save_end=false, maxiters=2e4)

@test length(sol) > 100

prob=ODEProblem(ż, z0, (0,5000.), (A=1, B=0.55, D=0.4), callback=cbf(3))
sol=solve(prob, Vern9(), abstol=1e-14, reltol=1e-14, save_everystep=false, save_start=false, save_end=false, maxiters=1e6)

@test length(sol) > 1500

f = function (du,u,p,t)
  du[1] = u[2]
  du[2] = -p[1]
end
function condition(u,t,integrator) # Event when event_f(u,t) == 0
  u[1]
end
function affect!(integrator)
  @test integrator.u[1] >= 0
  integrator.u[2] = -integrator.u[2]
end
cb2 = ContinuousCallback(condition,affect!)
tspan = (0.0,10000.0)
u0 = [50.0,0.0]
p = 9.8
prob = ODEProblem(f,u0,tspan,p)
sol = solve(prob,Tsit5(),callback=cb2)
@test minimum(sol') > -40

function vcondition!(out,u,t,integrator)
  out[1] = u[1]
  out[2] = u[2]
end

function vaffect!(integrator, event_idx)
  @test integrator.u[1] >= 0.0
  if event_idx == 1
    integrator.u[2] = -integrator.u[2]
  else
    integrator.p = 0.0
  end
end

u0 = [50.0,0.0]
tspan = (0.0,15.0)
p = 9.8
prob = ODEProblem(f,u0,tspan,p)
Vcb = VectorContinuousCallback(vcondition!,vaffect!, 2 , save_positions=(true,true))
sol = solve(prob,Tsit5(), callback=Vcb)

f = function (du,u,p,t)
  du[1] = u[2]
  du[2] = -9.81
end

function condition(u,t,integrator) # Event when event_f(u,t) == 0
  u[1]    # Event when height crosses from positive to negative
end

function affect_neg(integrator)
  @test integrator.u[1] >= 0.0
  integrator.u[2] = -0.8*integrator.u[2]
end

cb = ContinuousCallback(condition,nothing,affect_neg! = affect_neg)

u0 = [1.0,0.0]
tspan = (0.0, 3.0)
prob = ODEProblem(f,u0,tspan)
sol = solve(prob,Tsit5(),saveat=0.01,callback=cb)

f! = function (du,u,p,t)
  du[1] = u[2]
  du[2] = -p
end

function condition!(out,u,t,integrator)
  out[1] = u[1]
  out[2] = u[2]
end

function affect!(integrator, event_idx)
  if event_idx == 1
    integrator.u[2] = -integrator.u[2]
  else
    integrator.p = 0.0
  end
end

u0 = [50.0,0.0]
tspan = (0.0,15.0)

begin
    p = 9.8
    prob = ODEProblem(f!,u0,tspan,p)
    Vcb = VectorContinuousCallback(condition!,affect!, 2 , save_positions=(true,true))
    sol = solve(prob,Tsit5(), callback=Vcb)
end