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

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

Apply the service update to a list of clusters supplied. For more information on service
updates and applying them, see Applying the service updates.

# Arguments
- `cluster_names`: The cluster names to apply the updates.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ServiceUpdate"`: The unique ID of the service update
"""
function batch_update_cluster(
    ClusterNames; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "BatchUpdateCluster",
        Dict{String,Any}("ClusterNames" => ClusterNames);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function batch_update_cluster(
    ClusterNames,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "BatchUpdateCluster",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("ClusterNames" => ClusterNames), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    copy_snapshot(source_snapshot_name, target_snapshot_name)
    copy_snapshot(source_snapshot_name, target_snapshot_name, params::Dict{String,<:Any})

Makes a copy of an existing snapshot.

# Arguments
- `source_snapshot_name`: The name of an existing snapshot from which to make a copy.
- `target_snapshot_name`: A name for the snapshot copy. MemoryDB does not permit
  overwriting a snapshot, therefore this name must be unique within its context - MemoryDB or
  an Amazon S3 bucket if exporting.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"KmsKeyId"`: The ID of the KMS key used to encrypt the target snapshot.
- `"Tags"`: A list of tags to be added to this resource. A tag is a key-value pair. A tag
  key must be accompanied by a tag value, although null is accepted.
- `"TargetBucket"`: The Amazon S3 bucket to which the snapshot is exported. This parameter
  is used only when exporting a snapshot for external access. When using this parameter to
  export a snapshot, be sure MemoryDB has the needed permissions to this S3 bucket. For more
  information, see Step 2: Grant MemoryDB Access to Your Amazon S3 Bucket.
"""
function copy_snapshot(
    SourceSnapshotName,
    TargetSnapshotName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "CopySnapshot",
        Dict{String,Any}(
            "SourceSnapshotName" => SourceSnapshotName,
            "TargetSnapshotName" => TargetSnapshotName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function copy_snapshot(
    SourceSnapshotName,
    TargetSnapshotName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "CopySnapshot",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "SourceSnapshotName" => SourceSnapshotName,
                    "TargetSnapshotName" => TargetSnapshotName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Creates an Access Control List. For more information, see Authenticating users with Access
Contol Lists (ACLs).

# Arguments
- `aclname`: The name of the Access Control List.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Tags"`: A list of tags to be added to this resource. A tag is a key-value pair. A tag
  key must be accompanied by a tag value, although null is accepted.
- `"UserNames"`: The list of users that belong to the Access Control List.
"""
function create_acl(ACLName; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "CreateACL",
        Dict{String,Any}("ACLName" => ACLName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_acl(
    ACLName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "CreateACL",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("ACLName" => ACLName), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_cluster(aclname, cluster_name, node_type)
    create_cluster(aclname, cluster_name, node_type, params::Dict{String,<:Any})

Creates a cluster. All nodes in the cluster run the same protocol-compliant engine software.

# Arguments
- `aclname`: The name of the Access Control List to associate with the cluster.
- `cluster_name`: The name of the cluster. This value must be unique as it also serves as
  the cluster identifier.
- `node_type`: The compute and memory capacity of the nodes in the cluster.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"AutoMinorVersionUpgrade"`: When set to true, the cluster will automatically receive
  minor engine version upgrades after launch.
- `"Description"`: An optional description of the cluster.
- `"EngineVersion"`: The version number of the Redis engine to be used for the cluster.
- `"KmsKeyId"`: The ID of the KMS key used to encrypt the cluster.
- `"MaintenanceWindow"`: Specifies the weekly time range during which maintenance on the
  cluster is performed. It is specified as a range in the format ddd:hh24:mi-ddd:hh24:mi (24H
  Clock UTC). The minimum maintenance window is a 60 minute period.
- `"NumReplicasPerShard"`: The number of replicas to apply to each shard. The default value
  is 1. The maximum is 5.
- `"NumShards"`: The number of shards the cluster will contain. The default value is 1.
- `"ParameterGroupName"`: The name of the parameter group associated with the cluster.
- `"Port"`: The port number on which each of the nodes accepts connections.
- `"SecurityGroupIds"`: A list of security group names to associate with this cluster.
- `"SnapshotArns"`: A list of Amazon Resource Names (ARN) that uniquely identify the RDB
  snapshot files stored in Amazon S3. The snapshot files are used to populate the new
  cluster. The Amazon S3 object name in the ARN cannot contain any commas.
- `"SnapshotName"`: The name of a snapshot from which to restore data into the new cluster.
  The snapshot status changes to restoring while the new cluster is being created.
- `"SnapshotRetentionLimit"`: The number of days for which MemoryDB retains automatic
  snapshots before deleting them. For example, if you set SnapshotRetentionLimit to 5, a
  snapshot that was taken today is retained for 5 days before being deleted.
- `"SnapshotWindow"`: The daily time range (in UTC) during which MemoryDB begins taking a
  daily snapshot of your shard.  Example: 05:00-09:00  If you do not specify this parameter,
  MemoryDB automatically chooses an appropriate time range.
- `"SnsTopicArn"`: The Amazon Resource Name (ARN) of the Amazon Simple Notification Service
  (SNS) topic to which notifications are sent.
- `"SubnetGroupName"`: The name of the subnet group to be used for the cluster.
- `"TLSEnabled"`: A flag to enable in-transit encryption on the cluster.
- `"Tags"`: A list of tags to be added to this resource. Tags are comma-separated key,value
  pairs (e.g. Key=myKey, Value=myKeyValue. You can include multiple tags as shown following:
  Key=myKey, Value=myKeyValue Key=mySecondKey, Value=mySecondKeyValue.
"""
function create_cluster(
    ACLName, ClusterName, NodeType; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "CreateCluster",
        Dict{String,Any}(
            "ACLName" => ACLName, "ClusterName" => ClusterName, "NodeType" => NodeType
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_cluster(
    ACLName,
    ClusterName,
    NodeType,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "CreateCluster",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "ACLName" => ACLName,
                    "ClusterName" => ClusterName,
                    "NodeType" => NodeType,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_parameter_group(family, parameter_group_name)
    create_parameter_group(family, parameter_group_name, params::Dict{String,<:Any})

Creates a new MemoryDB parameter group. A parameter group is a collection of parameters and
their values that are applied to all of the nodes in any cluster. For more information, see
Configuring engine parameters using parameter groups.

# Arguments
- `family`: The name of the parameter group family that the parameter group can be used
  with.
- `parameter_group_name`: The name of the parameter group.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Description"`: An optional description of the parameter group.
- `"Tags"`: A list of tags to be added to this resource. A tag is a key-value pair. A tag
  key must be accompanied by a tag value, although null is accepted.
"""
function create_parameter_group(
    Family, ParameterGroupName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "CreateParameterGroup",
        Dict{String,Any}("Family" => Family, "ParameterGroupName" => ParameterGroupName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_parameter_group(
    Family,
    ParameterGroupName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "CreateParameterGroup",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "Family" => Family, "ParameterGroupName" => ParameterGroupName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_snapshot(cluster_name, snapshot_name)
    create_snapshot(cluster_name, snapshot_name, params::Dict{String,<:Any})

Creates a copy of an entire cluster at a specific moment in time.

# Arguments
- `cluster_name`: The snapshot is created from this cluster.
- `snapshot_name`: A name for the snapshot being created.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"KmsKeyId"`: The ID of the KMS key used to encrypt the snapshot.
- `"Tags"`: A list of tags to be added to this resource. A tag is a key-value pair. A tag
  key must be accompanied by a tag value, although null is accepted.
"""
function create_snapshot(
    ClusterName, SnapshotName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "CreateSnapshot",
        Dict{String,Any}("ClusterName" => ClusterName, "SnapshotName" => SnapshotName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_snapshot(
    ClusterName,
    SnapshotName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "CreateSnapshot",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "ClusterName" => ClusterName, "SnapshotName" => SnapshotName
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_subnet_group(subnet_group_name, subnet_ids)
    create_subnet_group(subnet_group_name, subnet_ids, params::Dict{String,<:Any})

Creates a subnet group. A subnet group is a collection of subnets (typically private) that
you can designate for your clusters running in an Amazon Virtual Private Cloud (VPC)
environment. When you create a cluster in an Amazon VPC, you must specify a subnet group.
MemoryDB uses that subnet group to choose a subnet and IP addresses within that subnet to
associate with your nodes. For more information, see Subnets and subnet groups.

# Arguments
- `subnet_group_name`: The name of the subnet group.
- `subnet_ids`: A list of VPC subnet IDs for the subnet group.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Description"`: A description for the subnet group.
- `"Tags"`: A list of tags to be added to this resource. A tag is a key-value pair. A tag
  key must be accompanied by a tag value, although null is accepted.
"""
function create_subnet_group(
    SubnetGroupName, SubnetIds; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "CreateSubnetGroup",
        Dict{String,Any}("SubnetGroupName" => SubnetGroupName, "SubnetIds" => SubnetIds);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_subnet_group(
    SubnetGroupName,
    SubnetIds,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "CreateSubnetGroup",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "SubnetGroupName" => SubnetGroupName, "SubnetIds" => SubnetIds
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    create_user(access_string, authentication_mode, user_name)
    create_user(access_string, authentication_mode, user_name, params::Dict{String,<:Any})

Creates a MemoryDB user. For more information, see Authenticating users with Access Contol
Lists (ACLs).

# Arguments
- `access_string`: Access permissions string used for this user.
- `authentication_mode`: Denotes the user's authentication properties, such as whether it
  requires a password to authenticate.
- `user_name`: The name of the user. This value must be unique as it also serves as the
  user identifier.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Tags"`: A list of tags to be added to this resource. A tag is a key-value pair. A tag
  key must be accompanied by a tag value, although null is accepted.
"""
function create_user(
    AccessString,
    AuthenticationMode,
    UserName;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "CreateUser",
        Dict{String,Any}(
            "AccessString" => AccessString,
            "AuthenticationMode" => AuthenticationMode,
            "UserName" => UserName,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function create_user(
    AccessString,
    AuthenticationMode,
    UserName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "CreateUser",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "AccessString" => AccessString,
                    "AuthenticationMode" => AuthenticationMode,
                    "UserName" => UserName,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes an Access Control List. The ACL must first be disassociated from the cluster before
it can be deleted. For more information, see Authenticating users with Access Contol Lists
(ACLs).

# Arguments
- `aclname`: The name of the Access Control List to delete

"""
function delete_acl(ACLName; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DeleteACL",
        Dict{String,Any}("ACLName" => ACLName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_acl(
    ACLName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DeleteACL",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("ACLName" => ACLName), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes a cluster. It also deletes all associated nodes and node endpoints

# Arguments
- `cluster_name`: The name of the cluster to be deleted

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"FinalSnapshotName"`: The user-supplied name of a final cluster snapshot. This is the
  unique name that identifies the snapshot. MemoryDB creates the snapshot, and then deletes
  the cluster immediately afterward.
"""
function delete_cluster(ClusterName; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DeleteCluster",
        Dict{String,Any}("ClusterName" => ClusterName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_cluster(
    ClusterName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "DeleteCluster",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("ClusterName" => ClusterName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes the specified parameter group. You cannot delete a parameter group if it is
associated with any clusters. You cannot delete the default parameter groups in your
account.

# Arguments
- `parameter_group_name`: The name of the parameter group to delete.

"""
function delete_parameter_group(
    ParameterGroupName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DeleteParameterGroup",
        Dict{String,Any}("ParameterGroupName" => ParameterGroupName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_parameter_group(
    ParameterGroupName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "DeleteParameterGroup",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("ParameterGroupName" => ParameterGroupName), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes an existing snapshot. When you receive a successful response from this operation,
MemoryDB immediately begins deleting the snapshot; you cannot cancel or revert this
operation.

# Arguments
- `snapshot_name`: The name of the snapshot to delete

"""
function delete_snapshot(SnapshotName; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DeleteSnapshot",
        Dict{String,Any}("SnapshotName" => SnapshotName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_snapshot(
    SnapshotName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "DeleteSnapshot",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("SnapshotName" => SnapshotName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes a subnet group. You cannot delete a default subnet group or one that is associated
with any clusters.

# Arguments
- `subnet_group_name`: The name of the subnet group to delete

"""
function delete_subnet_group(
    SubnetGroupName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DeleteSubnetGroup",
        Dict{String,Any}("SubnetGroupName" => SubnetGroupName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_subnet_group(
    SubnetGroupName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "DeleteSubnetGroup",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("SubnetGroupName" => SubnetGroupName), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Deletes a user. The user will be removed from all ACLs and in turn removed from all
clusters.

# Arguments
- `user_name`: The name of the user to delete

"""
function delete_user(UserName; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DeleteUser",
        Dict{String,Any}("UserName" => UserName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function delete_user(
    UserName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "DeleteUser",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("UserName" => UserName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a list of ACLs

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ACLName"`: The name of the ACL
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
"""
function describe_acls(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb("DescribeACLs"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET)
end
function describe_acls(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeACLs", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

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

Returns information about all provisioned clusters if no cluster identifier is specified,
or about a specific cluster if a cluster name is supplied.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ClusterName"`: The name of the cluster
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
- `"ShowShardDetails"`: An optional flag that can be included in the request to retrieve
  information about the individual shard(s).
"""
function describe_clusters(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DescribeClusters"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function describe_clusters(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeClusters", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

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

Returns a list of the available Redis engine versions.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"DefaultOnly"`: If true, specifies that only the default version of the specified engine
  or engine and major version combination is to be returned.
- `"EngineVersion"`: The Redis engine version
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
- `"ParameterGroupFamily"`: The name of a specific parameter group family to return details
  for.
"""
function describe_engine_versions(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DescribeEngineVersions"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function describe_engine_versions(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeEngineVersions",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns events related to clusters, security groups, and parameter groups. You can obtain
events specific to a particular cluster, security group, or parameter group by providing
the name as a parameter. By default, only the events occurring within the last hour are
returned; however, you can retrieve up to 14 days' worth of events if necessary.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Duration"`: The number of minutes worth of events to retrieve.
- `"EndTime"`: The end of the time interval for which to retrieve events, specified in ISO
  8601 format. Example: 2017-03-30T07:03:49.555Z
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
- `"SourceName"`: The identifier of the event source for which events are returned. If not
  specified, all sources are included in the response.
- `"SourceType"`: The event source to retrieve events for. If no value is specified, all
  events are returned.
- `"StartTime"`: The beginning of the time interval to retrieve events for, specified in
  ISO 8601 format. Example: 2017-03-30T07:03:49.555Z
"""
function describe_events(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DescribeEvents"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function describe_events(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeEvents", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

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

Returns a list of parameter group descriptions. If a parameter group name is specified, the
list contains only the descriptions for that group.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
- `"ParameterGroupName"`: The name of a specific parameter group to return details for.
"""
function describe_parameter_groups(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DescribeParameterGroups"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function describe_parameter_groups(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeParameterGroups",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns the detailed parameter list for a particular parameter group.

# Arguments
- `parameter_group_name`: he name of a specific parameter group to return details for.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
"""
function describe_parameters(
    ParameterGroupName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeParameters",
        Dict{String,Any}("ParameterGroupName" => ParameterGroupName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function describe_parameters(
    ParameterGroupName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "DescribeParameters",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("ParameterGroupName" => ParameterGroupName), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns details of the service updates

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ClusterNames"`: The list of cluster names to identify service updates to apply
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
- `"ServiceUpdateName"`: The unique ID of the service update to describe.
- `"Status"`: The status(es) of the service updates to filter on
"""
function describe_service_updates(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DescribeServiceUpdates"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function describe_service_updates(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeServiceUpdates",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns information about cluster snapshots. By default, DescribeSnapshots lists all of
your snapshots; it can optionally describe a single snapshot, or just the snapshots
associated with a particular cluster.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ClusterName"`: A user-supplied cluster identifier. If this parameter is specified, only
  snapshots associated with that specific cluster are described.
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
- `"ShowDetail"`: A Boolean value which if true, the shard configuration is included in the
  snapshot description.
- `"SnapshotName"`: A user-supplied name of the snapshot. If this parameter is specified,
  only this named snapshot is described.
- `"Source"`: If set to system, the output shows snapshots that were automatically created
  by MemoryDB. If set to user the output shows snapshots that were manually created. If
  omitted, the output shows both automatically and manually created snapshots.
"""
function describe_snapshots(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DescribeSnapshots"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function describe_snapshots(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeSnapshots", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

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

Returns a list of subnet group descriptions. If a subnet group name is specified, the list
contains only the description of that group.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
- `"SubnetGroupName"`: The name of the subnet group to return details for.
"""
function describe_subnet_groups(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "DescribeSubnetGroups"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end
function describe_subnet_groups(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeSubnetGroups",
        params;
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Returns a list of users.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Filters"`: Filter to determine the list of users to return.
- `"MaxResults"`: The maximum number of records to include in the response. If more records
  exist than the specified MaxResults value, a token is included in the response so that the
  remaining results can be retrieved.
- `"NextToken"`: An optional argument to pass in case the total number of records exceeds
  the value of MaxResults. If nextToken is returned, there are more results available. The
  value of nextToken is a unique pagination token for each page. Make the call again using
  the returned token to retrieve the next page. Keep all other arguments unchanged.
- `"UserName"`: The name of the user
"""
function describe_users(; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb("DescribeUsers"; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET)
end
function describe_users(
    params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "DescribeUsers", params; aws_config=aws_config, feature_set=SERVICE_FEATURE_SET
    )
end

"""
    failover_shard(cluster_name, shard_name)
    failover_shard(cluster_name, shard_name, params::Dict{String,<:Any})

Used to failover a shard

# Arguments
- `cluster_name`: The cluster being failed over
- `shard_name`: The name of the shard

"""
function failover_shard(
    ClusterName, ShardName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "FailoverShard",
        Dict{String,Any}("ClusterName" => ClusterName, "ShardName" => ShardName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function failover_shard(
    ClusterName,
    ShardName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "FailoverShard",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("ClusterName" => ClusterName, "ShardName" => ShardName),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Lists all available node types that you can scale to from your cluster's current node type.
When you use the UpdateCluster operation to scale your cluster, the value of the NodeType
parameter must be one of the node types returned by this operation.

# Arguments
- `cluster_name`: The name of the cluster you want to scale. MemoryDB uses the cluster name
  to identify the current node type being used by this cluster, and from that to create a
  list of node types you can scale up to.

"""
function list_allowed_node_type_updates(
    ClusterName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "ListAllowedNodeTypeUpdates",
        Dict{String,Any}("ClusterName" => ClusterName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_allowed_node_type_updates(
    ClusterName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "ListAllowedNodeTypeUpdates",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("ClusterName" => ClusterName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Lists all tags currently on a named resource. A tag is a key-value pair where the key and
value are case-sensitive. You can use tags to categorize and track your MemoryDB resources.
For more information, see Tagging your MemoryDB resources

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource for which you want the
  list of tags

"""
function list_tags(ResourceArn; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "ListTags",
        Dict{String,Any}("ResourceArn" => ResourceArn);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function list_tags(
    ResourceArn,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "ListTags",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("ResourceArn" => ResourceArn), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Modifies the parameters of a parameter group to the engine or system default value. You can
reset specific parameters by submitting a list of parameter names. To reset the entire
parameter group, specify the AllParameters and ParameterGroupName parameters.

# Arguments
- `parameter_group_name`: The name of the parameter group to reset.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"AllParameters"`: If true, all parameters in the parameter group are reset to their
  default values. If false, only the parameters listed by ParameterNames are reset to their
  default values.
- `"ParameterNames"`: An array of parameter names to reset to their default values. If
  AllParameters is true, do not use ParameterNames. If AllParameters is false, you must
  specify the name of at least one parameter to reset.
"""
function reset_parameter_group(
    ParameterGroupName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "ResetParameterGroup",
        Dict{String,Any}("ParameterGroupName" => ParameterGroupName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function reset_parameter_group(
    ParameterGroupName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "ResetParameterGroup",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("ParameterGroupName" => ParameterGroupName), 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})

A tag is a key-value pair where the key and value are case-sensitive. You can use tags to
categorize and track all your MemoryDB resources. When you add or remove tags on clusters,
those actions will be replicated to all nodes in the cluster. For more information, see
Resource-level permissions. For example, you can use cost-allocation tags to your MemoryDB
resources, Amazon generates a cost allocation report as a comma-separated value (CSV) file
with your usage and costs aggregated by your tags. You can apply tags that represent
business categories (such as cost centers, application names, or owners) to organize your
costs across multiple services. For more information, see Using Cost Allocation Tags.

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource to which the tags are to
  be added
- `tags`: A list of tags to be added to this resource. A tag is a key-value pair. A tag key
  must be accompanied by a tag value, although null is accepted.

"""
function tag_resource(ResourceArn, Tags; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "TagResource",
        Dict{String,Any}("ResourceArn" => ResourceArn, "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 memorydb(
        "TagResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("ResourceArn" => ResourceArn, "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})

Use this operation to remove tags on a resource

# Arguments
- `resource_arn`: The Amazon Resource Name (ARN) of the resource to which the tags are to
  be removed
- `tag_keys`: The list of keys of the tags that are to be removed

"""
function untag_resource(
    ResourceArn, TagKeys; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "UntagResource",
        Dict{String,Any}("ResourceArn" => ResourceArn, "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 memorydb(
        "UntagResource",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}("ResourceArn" => ResourceArn, "TagKeys" => TagKeys),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Changes the list of users that belong to the Access Control List.

# Arguments
- `aclname`: The name of the Access Control List

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"UserNamesToAdd"`: The list of users to add to the Access Control List
- `"UserNamesToRemove"`: The list of users to remove from the Access Control List
"""
function update_acl(ACLName; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "UpdateACL",
        Dict{String,Any}("ACLName" => ACLName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_acl(
    ACLName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "UpdateACL",
        Dict{String,Any}(mergewith(_merge, Dict{String,Any}("ACLName" => ACLName), params));
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Modifies the settings for a cluster. You can use this operation to change one or more
cluster configuration settings by specifying the settings and the new values.

# Arguments
- `cluster_name`: The name of the cluster to update

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"ACLName"`: The Access Control List that is associated with the cluster
- `"Description"`: The description of the cluster to update
- `"EngineVersion"`: The upgraded version of the engine to be run on the nodes. You can
  upgrade to a newer engine version, but you cannot downgrade to an earlier engine version.
  If you want to use an earlier engine version, you must delete the existing cluster and
  create it anew with the earlier engine version.
- `"MaintenanceWindow"`: The maintenance window to update
- `"NodeType"`: A valid node type that you want to scale this cluster up or down to.
- `"ParameterGroupName"`: The name of the parameter group to update
- `"ReplicaConfiguration"`: The number of replicas that will reside in each shard
- `"SecurityGroupIds"`: The SecurityGroupIds to update
- `"ShardConfiguration"`: The number of shards in the cluster
- `"SnapshotRetentionLimit"`: The number of days for which MemoryDB retains automatic
  cluster snapshots before deleting them. For example, if you set SnapshotRetentionLimit to
  5, a snapshot that was taken today is retained for 5 days before being deleted.
- `"SnapshotWindow"`: The daily time range (in UTC) during which MemoryDB begins taking a
  daily snapshot of your cluster.
- `"SnsTopicArn"`: The SNS topic ARN to update
- `"SnsTopicStatus"`: The status of the Amazon SNS notification topic. Notifications are
  sent only if the status is active.
"""
function update_cluster(ClusterName; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "UpdateCluster",
        Dict{String,Any}("ClusterName" => ClusterName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_cluster(
    ClusterName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "UpdateCluster",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("ClusterName" => ClusterName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

"""
    update_parameter_group(parameter_group_name, parameter_name_values)
    update_parameter_group(parameter_group_name, parameter_name_values, params::Dict{String,<:Any})

Updates the parameters of a parameter group. You can modify up to 20 parameters in a single
request by submitting a list parameter name and value pairs.

# Arguments
- `parameter_group_name`: The name of the parameter group to update.
- `parameter_name_values`: An array of parameter names and values for the parameter update.
  You must supply at least one parameter name and value; subsequent arguments are optional. A
  maximum of 20 parameters may be updated per request.

"""
function update_parameter_group(
    ParameterGroupName,
    ParameterNameValues;
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "UpdateParameterGroup",
        Dict{String,Any}(
            "ParameterGroupName" => ParameterGroupName,
            "ParameterNameValues" => ParameterNameValues,
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_parameter_group(
    ParameterGroupName,
    ParameterNameValues,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "UpdateParameterGroup",
        Dict{String,Any}(
            mergewith(
                _merge,
                Dict{String,Any}(
                    "ParameterGroupName" => ParameterGroupName,
                    "ParameterNameValues" => ParameterNameValues,
                ),
                params,
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Updates a subnet group. For more information, see Updating a subnet group

# Arguments
- `subnet_group_name`: The name of the subnet group

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"Description"`: A description of the subnet group
- `"SubnetIds"`: The EC2 subnet IDs for the subnet group.
"""
function update_subnet_group(
    SubnetGroupName; aws_config::AbstractAWSConfig=global_aws_config()
)
    return memorydb(
        "UpdateSubnetGroup",
        Dict{String,Any}("SubnetGroupName" => SubnetGroupName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_subnet_group(
    SubnetGroupName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "UpdateSubnetGroup",
        Dict{String,Any}(
            mergewith(
                _merge, Dict{String,Any}("SubnetGroupName" => SubnetGroupName), params
            ),
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end

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

Changes user password(s) and/or access string.

# Arguments
- `user_name`: The name of the user

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"AccessString"`: Access permissions string used for this user.
- `"AuthenticationMode"`: Denotes the user's authentication properties, such as whether it
  requires a password to authenticate.
"""
function update_user(UserName; aws_config::AbstractAWSConfig=global_aws_config())
    return memorydb(
        "UpdateUser",
        Dict{String,Any}("UserName" => UserName);
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end
function update_user(
    UserName,
    params::AbstractDict{String};
    aws_config::AbstractAWSConfig=global_aws_config(),
)
    return memorydb(
        "UpdateUser",
        Dict{String,Any}(
            mergewith(_merge, Dict{String,Any}("UserName" => UserName), params)
        );
        aws_config=aws_config,
        feature_set=SERVICE_FEATURE_SET,
    )
end


text:
### Reference state
using DocStringExtensions
using ..TemperatureProfiles
export ReferenceState, NoReferenceState, HydrostaticState
const TD = Thermodynamics
using CLIMAParameters.Planet: R_d, MSLP, cp_d, grav, T_surf_ref, T_min_ref

"""
    ReferenceState

Hydrostatic reference state, for example, used as initial
condition or for linearization.
"""
abstract type ReferenceState end

vars_state(m::ReferenceState, ::AbstractStateType, FT) = @vars()

atmos_init_aux!(
    ::ReferenceState,
    ::AtmosModel,
    aux::Vars,
    tmp::Vars,
    geom::LocalGeometry,
) = nothing

"""
    NoReferenceState <: ReferenceState

No reference state used
"""
struct NoReferenceState <: ReferenceState end

"""
    HydrostaticState{P,T} <: ReferenceState

A hydrostatic state specified by a virtual
temperature profile and relative humidity.

By default, this is a dry hydrostatic reference
state.
"""
struct HydrostaticState{P, FT} <: ReferenceState
    virtual_temperature_profile::P
    relative_humidity::FT
end
function HydrostaticState(
    virtual_temperature_profile::TemperatureProfile{FT},
) where {FT}
    return HydrostaticState{typeof(virtual_temperature_profile), FT}(
        virtual_temperature_profile,
        FT(0),
    )
end

vars_state(m::HydrostaticState, ::Auxiliary, FT) =
    @vars(ρ::FT, p::FT, T::FT, ρe::FT, ρq_tot::FT, ρq_liq::FT, ρq_ice::FT)

atmos_init_ref_state_pressure!(m, _...) = nothing
function atmos_init_ref_state_pressure!(
    m::HydrostaticState{P, F},
    atmos::AtmosModel,
    aux::Vars,
    geom::LocalGeometry,
) where {P, F}
    z = altitude(atmos, aux)
    _, p = m.virtual_temperature_profile(atmos.param_set, z)
    aux.ref_state.p = p
end

function atmos_init_aux!(
    m::HydrostaticState{P, F},
    atmos::AtmosModel,
    aux::Vars,
    tmp::Vars,
    geom::LocalGeometry,
) where {P, F}
    z = altitude(atmos, aux)
    T_virt, p = m.virtual_temperature_profile(atmos.param_set, z)
    FT = eltype(aux)
    _R_d::FT = R_d(atmos.param_set)
    k = vertical_unit_vector(atmos, aux)
    ∇Φ = ∇gravitational_potential(atmos, aux)

    # density computation from pressure ρ = -1/g*dpdz
    ρ = -k' * tmp.∇p / (k' * ∇Φ)
    aux.ref_state.ρ = ρ
    RH = m.relative_humidity
    phase_type = PhaseEquil
    (T, q_pt) = TD.temperature_and_humidity_given_TᵥρRH(
        atmos.param_set,
        T_virt,
        ρ,
        RH,
        phase_type,
    )

    # Update temperature to be exactly consistent with
    # p, ρ, and q_pt
    T = TD.air_temperature_from_ideal_gas_law(atmos.param_set, p, ρ, q_pt)
    q_tot = q_pt.tot
    q_liq = q_pt.liq
    q_ice = q_pt.ice
    if atmos.moisture isa DryModel
        ts = PhaseDry_ρT(atmos.param_set, ρ, T)
    else
        ts = PhaseEquil_ρTq(atmos.param_set, ρ, T, q_tot)
    end

    aux.ref_state.ρq_tot = ρ * q_tot
    aux.ref_state.ρq_liq = ρ * q_liq
    aux.ref_state.ρq_ice = ρ * q_ice
    aux.ref_state.T = T
    e_kin = F(0)
    e_pot = gravitational_potential(atmos.orientation, aux)
    aux.ref_state.ρe = ρ * total_energy(e_kin, e_pot, ts)
end

using ..MPIStateArrays: vars
using ..DGMethods: init_ode_state
using ..DGMethods.NumericalFluxes:
    CentralNumericalFluxFirstOrder,
    CentralNumericalFluxSecondOrder,
    CentralNumericalFluxGradient

"""
    PressureGradientModel

A mini balance law that is used to take the gradient of reference
pressure. The gradient is computed as ∇ ⋅(pI) and the calculation
uses the balance law interface to be numerically consistent with
the way this gradient is computed in the dynamics.
"""
struct PressureGradientModel <: BalanceLaw end
vars_state(::PressureGradientModel, ::Auxiliary, T) = @vars(p::T)
vars_state(::PressureGradientModel, ::Prognostic, T) = @vars(∇p::SVector{3, T})
vars_state(::PressureGradientModel, ::Gradient, T) = @vars()
vars_state(::PressureGradientModel, ::GradientFlux, T) = @vars()
function init_state_auxiliary!(
    m::PressureGradientModel,
    state_auxiliary::MPIStateArray,
    grid,
    direction,
) end
function init_state_prognostic!(
    ::PressureGradientModel,
    state::Vars,
    aux::Vars,
    localgeo,
    t,
) end
function flux_first_order!(
    ::PressureGradientModel,
    flux::Grad,
    state::Vars,
    auxstate::Vars,
    t::Real,
    direction,
)
    flux.∇p -= auxstate.p * I
end
flux_second_order!(::PressureGradientModel, _...) = nothing
source!(::PressureGradientModel, _...) = nothing

boundary_conditions(::PressureGradientModel) = ntuple(i -> nothing, 6)
boundary_state!(nf, ::Nothing, ::PressureGradientModel, _...) = nothing

∇reference_pressure(::NoReferenceState, state_auxiliary, grid) = nothing
function ∇reference_pressure(::ReferenceState, state_auxiliary, grid)
    FT = eltype(state_auxiliary)
    ∇p = similar(state_auxiliary; vars = @vars(∇p::SVector{3, FT}), nstate = 3)

    grad_model = PressureGradientModel()
    # Note that the choice of numerical fluxes doesn't matter
    # for taking the gradient of a continuous field
    grad_dg = DGModel(
        grad_model,
        grid,
        CentralNumericalFluxFirstOrder(),
        CentralNumericalFluxSecondOrder(),
        CentralNumericalFluxGradient(),
    )

    # initialize p
    ix_p = varsindex(vars(state_auxiliary), :ref_state, :p)
    grad_dg.state_auxiliary.data .= state_auxiliary.data[:, ix_p, :]

    # FIXME: this isn't used but needs to be passed in
    gradQ = init_ode_state(grad_dg, FT(0))

    grad_dg(∇p, gradQ, nothing, FT(0))
    return ∇p
end

ext: jl

max_forks_repo_name: jm-c/CLIMA


text:
"""
    function normalform(
                basispolys::Vector{Poly},
                tobereduced::Poly;
                ordering::Symbol=:input,
                randomized::Bool=true,
                rng::Rng=Random.MersenneTwister(42),
                loglevel::Logging.LogLevel=Logging.Warn
    ) where {Poly, Rng<:Random.AbstractRNG}

Computes the normal form of `tobereduced` w.r.t `basispolys`.
The latter is assumed to be a Groebner basis.

Uses the ordering on `basispolys` by default.
If `ordering` is explicitly specialized, it takes precedence.
*(On the fly ordering change not implemented yet :D)*

The algorithm is randomized by default, but
this can be changed with the `randomized` param.
*(Derandomized version not implemented yet :D)*

"""
function normalform(
            basispolys::Vector{Poly},
            tobereduced::Poly;
            ordering::Symbol=:input,
            rng::Rng=Random.MersenneTwister(42),
            loglevel::LogLevel=Logging.Warn
            ) where {Poly, Rng<:Random.AbstractRNG}

    first(normalform(
            basispolys, [tobereduced],
            ordering=ordering, rng=rng, loglevel=loglevel)
    )
end

function normalform(
            basispolys::Vector{Poly},
            tobereduced::Vector{Poly};
            ordering::Symbol=:input,
            rng::Rng=Random.MersenneTwister(42),
            loglevel::LogLevel=Logging.Warn
            ) where {Poly, Rng<:Random.AbstractRNG}

    #= set the logger =#
    prev_logger = Logging.global_logger(ConsoleLogger(stderr, loglevel))

    #= extract ring information, exponents and coefficients
       from input basis polynomials =#
    # Copies input, so that polys would not be changed itself.
    ring1, basisexps, basiscoeffs = convert_to_internal(basispolys, ordering)
    ring2, tbrexps, tbrcoeffs = convert_to_internal(tobereduced, ordering)

    @assert ring1.nvars == ring2.nvars && ring1.ch == ring2.ch && ring1.ord == ring2.ord
    ring = ring1
    # We assume basispolys is already a Groebner basis! #

    #= compute the groebner basis =#
    bexps, bcoeffs = normal_form_f4(
                        ring, basisexps, basiscoeffs,
                        tbrexps, tbrcoeffs, rng)

    #=
    Assuming ordering of `bexps` here matches `ring.ord`
    =#

    #= revert logger =#
    Logging.global_logger(prev_logger)

    # ring contains ordering of computation, it is the requested ordering
    #= convert result back to representation of input =#
    convert_to_output(ring, tobereduced, bexps, bcoeffs)
end


text:
import Base: iterate, length, pairs

export pairs, sites, site, nbodies

abstract type AbstractIterator end

inc(i::T) where {T <: Integer} = i + T(1)

# -------------- iterator over pairs ---------------

pairs(nlist::PairList) = PairIterator(nlist)

struct PairIterator{T,TI} <: AbstractIterator
   nlist::PairList{T,TI}
end

_item(it::PairIterator, i::Integer) =
      (it.nlist.i[i], it.nlist.j[i], _getR(it.nlist, i))
iterate(it::PairIterator{T,TI}) where {T,TI} =
   npairs(it.nlist) > 0 ? (_item(it, 1), TI(1)) : nothing
iterate(it::PairIterator, i::Integer) =
   i >= npairs(it.nlist) ? nothing : (_item(it, inc(i)), inc(i))
length(it::PairIterator) = npairs(it.nlist)

# -------------- iterator over sites ---------------

sites(nlist::PairList) = SiteIterator(nlist)

struct SiteIterator{T,TI}  <: AbstractIterator
   nlist::PairList{T,TI}
end

_item(it::SiteIterator, i::Integer) = (i, neigs(it.nlist, i)...)
iterate(it::SiteIterator{T,TI}) where {T,TI} = _item(it, 1), one(TI)
iterate(it::SiteIterator, i::Integer) =
   i >= length(it) ? nothing : (_item(it, i+1), inc(i))
length(it::SiteIterator) = nsites(it.nlist)


text:
using HiQGA.transD_GP, PyPlot
## model fixed parts, i.e., air, but only to be compatible with AEM ...
zfixed   = [-1e5]
ρfixed   = [1e12]
nmax = 200
# z grid spec starts, the first z and first ρ will be unused in MT
zstart = 0.
extendfrac, dz = 1.028, 10
zall, znall, zboundaries = transD_GP.setupz(zstart, extendfrac, dz=dz, n=50, showplot=true)
z, ρ, nfixed = transD_GP.makezρ(zboundaries; zfixed=zfixed, ρfixed=ρfixed)
## fill in detail in ohm-m
ρ[(z.>=zstart) .& (z.<50)] .= 10.
ρ[(z.>=50)  .& (z.<100)] .= 20
ρ[(z.>=100) .& (z.<250)] .= 50
ρ[(z.>=250) .& (z.<300)] .= 5
ρ[(z.>=300) .& (z.<500)] .= 100
ρ[z.>=500] .= 800
##
T = 10 .^range(-3, 0, length=10)
F = transD_GP.MT1DInversion.create_synthetic(ρ =  ρ[2:end], zboundaries = zboundaries,
                                            freqs = 1 ./T, rseed=125, showplot=true, noisefrac=0.05, logscaledepth=false)
## now apply a stretch prior
# remember there must be a ρlow and ρhigh at every zall
ρlow, ρhigh = -0.5*ones(size(zall)), zall*0.001 .+ 2.5
Δ = ρhigh - ρlow
F = transD_GP.MT1DInversion.makestretchop(F, ρlow=ρlow, Δ=Δ)
ax = gcf().axes[1]
transD_GP.MT1DInversion.plotpriorenv(F, ax=ax, lc = "r")
F.stretch = true # if wanting to toggle stretch priors

max_stars_repo_name: GeoscienceAustralia/HiQGA

max_issues_repo_name: GeoscienceAustralia/HiQGA

max_forks_repo_name: GeoscienceAustralia/HiQGA


text:
if nworkers()<=1
	addprocs(4);
end

using jInv.Mesh
using jInv.Utils
using jInv.InverseSolve
using jInvSeismic.EikonalInv
using jInvSeismic.Utils
using MAT
using DelimitedFiles
using Statistics

#############################################################################################################
modelDir = "../examples";

dataDir = pwd();
include("../../examples/TravelTimeTomography/drivers/prepareTravelTimeDataFiles.jl");
include("../../examples/TravelTimeTomography/drivers/setupTravelTimeTomography.jl");

########################################################################################################
######################################## for SEG 256X512 ###############################################
#######################################################################################################
dim     = 2;
pad     = 1;
jump    = 32;
offset  = 256;
(m,Minv,mref,boundsHigh,boundsLow) = readModelAndGenerateNodalMeshMref(modelDir,"SEGmodel2Dsalt.dat",dim,pad,[0.0,13.5,0.0,4.2],[64,32]);
dataFilenamePrefix = string(dataDir,"/DATA_SEG",tuple((Minv.n.+1)...));

prepareTravelTimeDataFiles(m,Minv,mref,boundsHigh,boundsLow,dataFilenamePrefix,pad,jump,offset);
resultsFilenamePrefix = "";
(Q,P,pMisRFs,SourcesSubInd,contDiv,Iact,sback,mref,boundsHigh,boundsLow,resultsFilename) = setupTravelTimeTomography(m,dataFilenamePrefix, resultsFilenamePrefix);

########################################################################################################
##### Set up Inversion #################################################################################
########################################################################################################
maxStep=0.1*maximum(boundsHigh);
a = minimum(boundsLow);
b = maximum(boundsHigh);
function modfun(m)
	bm,dbm = getBoundModel(m,a,b);
	bs,dbs = velocityToSlowSquared(bm);
	dsdm = dbm*dbs;
	return bs,dsdm;
end
mref = getBoundModelInv(mref,a,b);
boundsHigh = boundsHigh*10000000.0;
boundsLow = -boundsLow*100000000.0

cgit  = 2;
maxit = 1;
alpha = 1e+0;
pcgTol = 1e-1;

HesPrec=getSSORCGRegularizationPreconditioner(1.0,1e-5,2)

################################################# GIT VERSION OF JINV #################################################

regparams = [1.0,1.0,1.0,1e-2];
regfun(m, mref, M) = wdiffusionRegNodal(m, mref, M, Iact=Iact, C = regparams);

pInv = getInverseParam(Minv,modfun,regfun,alpha,mref[:],boundsLow,boundsHigh,
                     maxStep=maxStep,pcgMaxIter=cgit,pcgTol=pcgTol,
					 minUpdate=1e-3, maxIter = maxit,HesPrec=HesPrec);

mc,Dc,flag = projGNCG(mref[:],pInv,pMisRFs,indCredit = []);

clear!(pMisRFs);
#############################################################################################
rm("DATA_SEG(66, 33)_travelTime.dat");
rm("DATA_SEG(66, 33)_rcvMap.dat");
rm("DATA_SEG(66, 33)_srcMap.dat");
rm("DATA_SEG(66, 33)_PARAM.mat");
rm("jInv.out");


text:
using HOODESolver: PolyExp, coeffs, derivative, integrate
using Test
function testPolyExp()

    @time @testset "test PolyExp" begin
        pol = PolyExp(convert( Vector{Complex{Rational{BigInt}}}, [2//3, 5//23, 57//4, 1//5]), big(im//7), big(1//10+0im) )

        c_res = coeffs(pol)

 #       println("pol=$(string(pol))")

        @test [2//3, 5//23, 57//4, 1//5, im//7, 1//10 ] == c_res

        polder = derivative(pol)

        c_resder = coeffs(polder)

        @test [2im//21+5//23, 5im//(23*7)+ 57//2, 57im//(4*7)+3//5, 1im//35,  im//7, 1//10 ] == c_resder

        polintder = integrate(polder)
        c_resintder = coeffs(polintder)

        @test c_res == c_resintder

        p1 = PolyExp([1.0, 2, 3], 3.4, 1.1)
        p2 = PolyExp([0.5, -1, 1], 1.3, 0.245)

        c_resmul = coeffs(p1*p2)
        @test isapprox([0.5, 0.0, 0.5, -1.0, 3.0, 4.7, 1.345], c_resmul, atol=1e-15)

        p3 = PolyExp([0.2, 0, 3.0, 2.0], 1.3, 0.245)

        c_resadd = coeffs(p2 + p3)
        @test isapprox([0.7, -1.0, 4.0, 2.0, 1.3, 0.245], c_resadd, atol=1e-15)
    end
end

testPolyExp()


text:
using ParameterizedFunctions, OrdinaryDiffEq, DiffEqParamEstim
using BlackBoxOptim, NLopt, Plots,QuadDIRECT
gr(fmt=:png)

loc_bounds = Tuple{Float64,Float64}[(0, 1), (0, 1), (0, 1), (0, 1)]
glo_bounds = Tuple{Float64,Float64}[(0, 5), (0, 5), (0, 5), (0, 5)]
loc_init = [0.5,0.5,0.5,0.5]
glo_init = [2.5,2.5,2.5,2.5]

fitz = @ode_def FitzhughNagumo begin
  dv = v - v^3/3 -w + l
  dw = τinv*(v +  a - b*w)
end a b τinv l

p = [0.7,0.8,0.08,0.5]              # Parameters used to construct the dataset
r0 = [1.0; 1.0]                     # initial value
tspan = (0.0, 30.0)                 # sample of 3000 observations over the (0,30) timespan
prob = ODEProblem(fitz, r0, tspan,p)
tspan2 = (0.0, 3.0)                 # sample of 300 observations with a timestep of 0.01
prob_short = ODEProblem(fitz, r0, tspan2,p)

dt = 30.0/3000
tf = 30.0
tinterval = 0:dt:tf
t  = collect(tinterval)

h = 0.01
M = 300
tstart = 0.0
tstop = tstart + M * h
tinterval_short = 0:h:tstop
t_short = collect(tinterval_short)

#Generate Data
data_sol_short = solve(prob_short,Vern9(),saveat=t_short,reltol=1e-9,abstol=1e-9)
data_short = convert(Array, data_sol_short) # This operation produces column major dataset obs as columns, equations as rows
data_sol = solve(prob,Vern9(),saveat=t,reltol=1e-9,abstol=1e-9)
data = convert(Array, data_sol)

plot(data_sol_short)

plot(data_sol)

obj_short = build_loss_objective(prob_short,Tsit5(),L2Loss(t_short,data_short),tstops=t_short)
res1 = bboptimize(obj_short;SearchRange = glo_bounds, MaxSteps = 7e3)
# Lower tolerance could lead to smaller fitness (more accuracy)

obj_short = build_loss_objective(prob_short,Tsit5(),L2Loss(t_short,data_short),tstops=t_short,reltol=1e-9)
res1 = bboptimize(obj_short;SearchRange = glo_bounds, MaxSteps = 7e3)
# Change in tolerance makes it worse

obj_short = build_loss_objective(prob_short,Vern9(),L2Loss(t_short,data_short),tstops=t_short,reltol=1e-9,abstol=1e-9)
res1 = bboptimize(obj_short;SearchRange = glo_bounds, MaxSteps = 7e3)
# using the moe accurate Vern9() reduces the fitness marginally and leads to some increase in time taken

obj_short = build_loss_objective(prob_short,Vern9(),L2Loss(t_short,data_short),tstops=t_short,reltol=1e-9,abstol=1e-9)

opt = Opt(:GN_ORIG_DIRECT_L, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[5.0,5.0,5.0,5.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,glo_init)

opt = Opt(:GN_CRS2_LM, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[5.0,5.0,5.0,5.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,glo_init)

opt = Opt(:GN_ISRES, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[5.0,5.0,5.0,5.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,glo_init)

opt = Opt(:GN_ESCH, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[5.0,5.0,5.0,5.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,glo_init)

opt = Opt(:LN_BOBYQA, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LN_NELDERMEAD, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LD_SLSQP, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LN_COBYLA, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LN_NEWUOA_BOUND, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LN_PRAXIS, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LN_SBPLX, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LD_MMA, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj_short.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

obj = build_loss_objective(prob,Vern9(),L2Loss(t,data),tstops=t,reltol=1e-9,abstol=1e-9)
res1 = bboptimize(obj;SearchRange = glo_bounds, MaxSteps = 4e3)

opt = Opt(:GN_ORIG_DIRECT_L, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[5.0,5.0,5.0,5.0])
min_objective!(opt, obj.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,glo_init)

opt = Opt(:GN_CRS2_LM, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[5.0,5.0,5.0,5.0])
min_objective!(opt, obj.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 20000)
@time (minf,minx,ret) = NLopt.optimize(opt,glo_init)

opt = Opt(:GN_ISRES, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[5.0,5.0,5.0,5.0])
min_objective!(opt, obj.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 50000)
@time (minf,minx,ret) = NLopt.optimize(opt,glo_init)

opt = Opt(:GN_ESCH, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[5.0,5.0,5.0,5.0])
min_objective!(opt, obj.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 20000)
@time (minf,minx,ret) = NLopt.optimize(opt,glo_init)

opt = Opt(:LN_BOBYQA, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LN_NELDERMEAD, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj.cost_function2)
xtol_rel!(opt,1e-9)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

opt = Opt(:LD_SLSQP, 4)
lower_bounds!(opt,[0.0,0.0,0.0,0.0])
upper_bounds!(opt,[1.0,1.0,1.0,1.0])
min_objective!(opt, obj.cost_function2)
xtol_rel!(opt,1e-12)
maxeval!(opt, 10000)
@time (minf,minx,ret) = NLopt.optimize(opt,loc_init)

obj_short = build_loss_objective(prob_short,Tsit5(),L2Loss(t_short,data_short),tstops=t_short)
lower = [0,0,0,0]
upper = [1,1,1,1]
splits = ([0,0.3,0.7],[0,0.3,0.7],[0,0.3,0.7],[0,0.3,0.7])
@time root, x0 = analyze(obj_short,splits,lower,upper)

minimum(root)

obj = build_loss_objective(prob,Vern9(),L2Loss(t,data),tstops=t,reltol=1e-9,abstol=1e-9)
lower = [0,0,0,0]
upper = [5,5,5,5]
splits = ([0,0.5,1],[0,0.5,1],[0,0.5,1],[0,0.5,1])
@time root, x0 = analyze(obj_short,splits,lower,upper)

minimum(root)


text:
# Tests the GeoUnits
using Test
using GeoParams

@testset "Units" begin

# test creating structures
CharUnits_GEO   =   GEO_units(viscosity=1e19, length=1000km);
@test CharUnits_GEO.length  ==  1000km
@test CharUnits_GEO.Pa      ==  10000000Pa
@test CharUnits_GEO.Mass    ==  1.0e37kg
@test CharUnits_GEO.Time    ==  1.0e12s
@test CharUnits_GEO.Length  ==  1000000m

CharUnits_SI   =   SI_units();
@test CharUnits_SI.length   ==  1000m
@test CharUnits_SI.Pa       ==  10Pa

CharUnits_NO   =   NO_units();
@test CharUnits_NO.length   ==  1
@test CharUnits_NO.Pa       ==  1

# test nondimensionization of various parameters
@test Nondimensionalize(10cm/yr,CharUnits_GEO) ≈ 0.0031688087814028945   rtol=1e-10
@test Nondimensionalize(10cm/yr,CharUnits_SI) ≈ 3.168808781402895e7   rtol=1e-10

A = 10MPa*s^(-1)   # should give 1e12 in ND units
@test Nondimensionalize(A,CharUnits_GEO)  ≈ 1e12

A = 10Pa^1.2*s^(-1)
@test Nondimensionalize(A,CharUnits_GEO)  ≈ 39810.71705534975

CharUnits   =   GEO_units(viscosity=1e23, length=100km, stress=0.00371MPa);
@test Nondimensionalize(A,CharUnits)  ≈ 1.40403327e16

A = (1.58*10^(-25))*Pa^(-4.2)*s^(-1)        # calcite
@test Nondimensionalize(A,CharUnits_GEO)  ≈ 3.968780561785161e16

R=8.314u"J/mol/K"
@test Nondimensionalize(R,CharUnits_SI)  ≈ 8.314e-7

# test Dimensionalize
v_ND      =   Nondimensionalize(3cm/yr, CharUnits_GEO);
@test Dimensionalize(v_ND, cm/yr, CharUnits_GEO) == 3.0cm/yr

# Test the GeoUnit struct
x=GeoUnit(8.1cm/yr)
@test  x.val==8.1cm/yr
Nondimensionalize!(x,CharUnits_GEO)
@test  x.val≈ 0.002566735112936345 rtol=1e-8        # Nondimensionalize a single value
Dimensionalize!(x,CharUnits_GEO)
@test  x.val==8.1cm/yr                              # Dimensionalize again

y   =   x+2cm/yr
@test  y.val==10.1cm/yr                             # errors

xx  =GeoUnit([8.1cm/yr; 10cm/yr]);
@test  xx.val==[8.1cm/yr; 10cm/yr]
yy=xx/(1cm/yr);                                         # transfer to no-unt

z=GeoUnit([100km 1000km 11km; 10km 2km 1km], km);       # array
@test z/1km*1.0 == [100.0 1000.0 11.0; 10.0 2.0 1.0]    # The division by 1km transfer it to a GeoUnit structure with no units; the multiplying with a float creates a float array

zz = GeoUnit([1:10]km)

# Test non-dimensionalisation if z is an array
@test Nondimensionalize!(z,CharUnits_GEO)==[0.1   1.0    0.011; 0.01  0.002  0.001]

Dimensionalize!(z,CharUnits_GEO)
@test z.val==[100km 1000km 11km; 10km 2km 1km]          # transform back

# test extracting a value from a GeoUnit array
@test z[2,2] == 2.0km

# test setting a new value
z[2,1]=3km
@test z[2,1] == 3.0km
end


text:
#=

  Test of negative binomial.

  From BLOG documentation:
  """
  NegativeBinomial distribution generates the number of failures until the rth success
  in a sequence of independent Bernoulli trials each with probability of success p.

  Example: The following code defines a random function symbol x distributed according to a
  Negative Binomial distribution with probability of success p = 0.8 and number of failures r = 2.
  random Integer x ~ NegativeBinomial(2, 0.8);
  """

  https://stattrek.com/probability-distributions/negative-binomial.aspx
  """
  Bob is a high school basketball player. He is a 70% free throw shooter. That means his probability
  of making a free throw is 0.70. During the season, what is the probability that Bob makes his
  third free throw on his fifth shot?

  Solution: This is an example of a negative binomial experiment. The probability of success (P)
  is 0.70, the number of trials (x) is 5, and the number of successes (r) is 3.

  To solve this problem, we enter these values into the negative binomial formula.

  b*(x; r, P) = x-1Cr-1 * Pr * Qx - r
  b*(5; 3, 0.7) = 4C2 * 0.73 * 0.32
  b*(5; 3, 0.7) = 6 * 0.343 * 0.09 = 0.18522

  Thus, the probability that Bob will make his third successful free throw on his fifth shot is 0.18522.
  """

  The distribution of y give a fair estimation
  0 =>   55089  0.344306
  1 =>   49144  0.307150
  2 =>   29557  0.184731 <---
  3 =>   14803  0.092519
  4 =>    6683  0.041769
  5 =>    2829  0.017681
  6 =>    1157  0.007231
  7 =>     476  0.002975
  8 =>     166  0.001038
  9 =>      55  0.000344
 10 =>      30  0.000188
 11 =>      10  0.000063
 12 =>       1  0.000006

  Cf ~/blog/negative_binomial_test.blog
     ~/webppl/negative_binomial_test.wppl

=#

# using Memoization
using Turing, StatsPlots, DataFrames
using ReverseDiff, Zygote, Tracker
using Printf
# Turing.setadbackend(:reversediff)
# Turing.setadbackend(:zygote)
# Turing.setadbackend(:tracker)

include("jl_utils.jl")

# Note: This does not really require Turing.
# The following is easier...
#=
# julia> rand(NegativeBinomial(3,0.7),100000)|>make_hash|>sort
OrderedCollections.OrderedDict{Any,Any} with 13 entries:
  0  => 34214
  1  => 30817
  2  => 18522
  3  => 9322
  4  => 4238
  5  => 1740
  6  => 694
  7  => 302
  8  => 96
  9  => 37
  10 => 11
  11 => 6
  13 => 1
=#
@model function negative_binomial_test()
  y ~ NegativeBinomial(3,0.7)
end

model = negative_binomial_test()

num_chains = 4

# chains = sample(model, Prior(), MCMCThreads(), 40_000, num_chains)
#
# chains = sample(model, MH(), 40_000)
chains = sample(model, MH(), MCMCThreads(), 40_000, num_chains)

# chains = sample(model, PG(20), MCMCThreads(), 40_000, num_chains)
# chains = sample(model, PG(20), 1_000)

# chains = sample(model, IS(), MCMCThreads(), 40_000, num_chains)
# chains = sample(model, IS(), 10_000)

# chains = sample(model, SMC(), MCMCThreads(), 40_000, num_chains)
# chains = sample(model, SMC(), 10_000)

# chains = sample(model, NUTS(1000,0.65), 40_000)
# chains = sample(model, NUTS(1000,0.65), MCMCThreads(), 40_000, num_chains)

# chains = sample(model, Gibbs(MH(:n),NUTS(1000,0.65,:y)), MCMCThreads(), 1_000, num_chains)
# chains = sample(model, Gibbs(MH(:n),NUTS(10,0.65,:y)), 1_000)

display(chains)

show_var_dist(chains,:y)

max_stars_repo_name: Wikunia/hakank

max_issues_repo_name: Wikunia/hakank

max_forks_repo_name: Wikunia/hakank


text:
using Random
Random.seed!(5)
using Statistics, ZigZagBoomerang, LinearAlgebra, Test, SparseArrays
n = 60
d = n*(n+1)÷2
N = 1000
K = 20
T = 800.0

outer(x) = x*x'
function backform(u, 𝕀)
    L = zeros(𝕀[end][1], 𝕀[end][2])
    for (x, i) in zip(u, 𝕀)
        L[i] = x
    end
    L
end
transform(L, 𝕀) = L[𝕀]

const σ2 = 1.0
const γ0 = 0.1
dia = -0.3ones(n-1)
Γtrue = sparse(SymTridiagonal(1.0ones(n), dia))

Ltrue_ = cholesky(Γtrue).L
Y = Ltrue_\randn(n, N)
YY = Y*Y'
Ltrue = L = sparse(Ltrue_)
# Compute an unbiased estimate of the i'th partial derivative of the negative loglikelihood in a smart way
function ϕ(L, Y)
   # L = reshape(x, d, d)
   sum(2*(diag(L) .- 1.0).^2)/2 - N*sum(log.(diag(L).^2)) + tr(Y'*(L*(L'*Y)))/2
end
using ForwardDiff
ϕ(Ltrue, Y)
utrue_ = Vector(vec(Ltrue))
@test tr(YY*L*L') ≈ sum(Y[:, i]'*L*L'*Y[:,i] for i in 1:N)

𝕀 = [c for c in CartesianIndices((n,n)) if c[1] >= c[2]]
𝕁 = [[(i,CartesianIndex(c[1], c2[1])) for (i,c2) in enumerate(𝕀) if c2[1] >= c[2] && c[2] == c2[2]] for c in 𝕀]
utrue = Vector(L[𝕀])
function ∇ϕ(u, i, YY, (𝕀, 𝕁), N)
    c = 0.0
    for (j, c2) in 𝕁[i]
        #c += YY[ii[1], c2[1]] * u[j] #L[j,ii[2]]
         c += YY[c2] * u[j] #L[j,ii[2]]

    end
    if 𝕀[i][1] == 𝕀[i][2]
        c += -N/u[i] #+ 2(u[i]-1)
    end
    c
end
∇ϕ(utrue, 2, YY,  (𝕀, 𝕁), N)

t0 = 0.0

x0 = utrue + 0.01*randn(d) # jiggle the starting point to see convergence

#te = reshape(ForwardDiff.gradient(u -> ϕ(reshape(u, n, n), Y), backform(x0, 𝕀)[:]), n, n)
#@test norm(Vector(te[𝕀]) - [∇ϕ(x0, i, YY, (𝕀, 𝕁), N) for i in 1:d]) < 10d^2*eps()

θ0 = rand([-1.0, 1.0], d)

# Graphical structure of posterior
G = [i => first.(j) for (i,j) in enumerate(𝕁)]

# precision bounds
c = 10ones(d)
dt = T/500
Γ̂ = sparse(1.0I(d))
#L̂ = cholesky(sparse(SymTridiagonal(cov(Y')))).L
#μ̂ = transform(Matrix(sparse(L̂)), 𝕀)
L̂ = cholesky(cov(Y')).L
μ̂ = transform(L̂, 𝕀)

Z = ZigZag(Γ̂, μ̂)
κ = 0.01ones(d)

trc, _ = @time ZigZagBoomerang.sspdmp(∇ϕ, t0, x0, θ0, T, c, G, Z, κ, YY, (𝕀, 𝕁), N; structured=true, adapt=true, progress=true)

J = [1,2,5]
subtrc = subtrace(trc, J)

ts, xs = ZigZagBoomerang.sep(collect(discretize(subtrc, dt)))
#ts, xs = ZigZagBoomerang.sep(subtrc)

# posterior mean
u = mean(trc)
Lhat = backform(u, 𝕀)
utrue - u

ina(i) = "$(𝕀[J[i]][1]),$(𝕀[J[i]][2])"
fig = Figure(resolution=(1000,1000))
ax = fig[1,1:3] = Axis(fig, title="Error Gamma")
fig[2,1] = Axis(fig, title="x$(ina(1))")
fig[2,2] = Axis(fig, title="x$(ina(2))")
fig[2,3] = Axis(fig, title="x$(ina(3))")
heatmap!(ax, (Matrix(Γtrue) - outer(Lhat)), colormap=:vik, colorrange=[-1/4,1/4])
lines!(fig[2,1], ts, getindex.(xs, 1))
lines!(fig[2,1], ts, fill(utrue[J[1]], length(ts)), color=:green)
lines!(fig[2,2], ts, getindex.(xs, 2))
lines!(fig[2,2], ts, fill(utrue[J[2]], length(ts)), color=:green)
lines!(fig[2,3], ts, getindex.(xs, 3))
lines!(fig[2,3], ts, fill(utrue[J[3]], length(ts)), color=:green)
display(fig)

using FileIO
save("precision.png", fig)


text:
function aetherlang_repr(x)
    try
        return sprint(aetherlang_show, x)
    catch
        return repr(x)
    end
end
function Base.indexin(s1::String, s2::String)
    """returns positions of elements of s1 in s2."""
    indexin([c for c in s1], [c for c in s2])
end
function aetherlang_show(io::IO, c::Char)
    print(io, "\""*c*"\"")
end

max_stars_repo_name: Aetherlang/aetherlang

max_issues_repo_name: gojakuch/aetherlang

max_forks_repo_name: gojakuch/aetherlang


text:
mutable struct TDMSbuf
  flags::UInt32
  nsos::UInt64
  rdos::UInt64
  n_ch::UInt32
  ts::Int64
  fs::Float64
  ox::Float64
  oy::Float64
  oz::Float64
  name::String
  hdr::Dict{String, Any}

  TDMSbuf(
        flags::UInt32,
        nsos::UInt64,
        rdos::UInt64,
        n_ch::UInt32,
        ts::Int64,
        fs::Float64,
        ox::Float64,
        oy::Float64,
        oz::Float64,
        name::String,
        hdr::Dict{String, Any}
      ) = new(flags, nsos, rdos, n_ch, ts, fs, ox, oy, oz, name, hdr)
end


text:
kappa(κ::K, ::Missing) where K <: Kernel{T} where T = missing

function kappamatrix!(
    κ::Kernel{T},
    P#::AbstractMatrix{mT}
) where mT <: Union{Missing, T} where T <: AbstractFloat
    for i in eachindex(P)
        @inbounds P[i] = kappa(κ, P[i])
    end
    return P
end

function symmetric_kappamatrix!(
    κ::Kernel{T},
    P::AbstractMatrix{mT},
    symmetrize::Bool
) where {mT <: Union{Missing, T}} where {T<:AbstractFloat}
    if !((n = size(P,1)) == size(P,2))
        throw(DimensionMismatch("Pairwise matrix must be square."))
    end
    for j = 1:n, i = (1:j)
        @inbounds P[i,j] = kappa(κ, P[i,j])
    end

    symmetrize && copytri!(P, 'U', false)

    return P
end

"""
    kernelmatrix!(σ::Orientation, K::Matrix, κ::Kernel, X::Matrix, symmetrize::Bool)

In-place version of `kernelmatrix` where pre-allocated matrix `K` will be overwritten
with the kernel matrix.
"""
function kernelmatrix!(
    σ::Orientation,
    K::Matrix{Union{Missing, T}},
    κ::Kernel{T},
    X::AbstractMatrix{mT1},
    symmetrize::Bool
) where
    {mT1 <: Union{Missing, T}} where
    {T <: AbstractFloat}

    f = basefunction(κ)

    basematrix!(σ, K, f, X, false)
    symmetric_kappamatrix!(κ, K, symmetrize)

    return K
end

"""
    kernelmatrix!(σ::Orientation, K::Matrix, κ::Kernel, X::Matrix, Y::Matrix)

In-place version of `kernelmatrix` where pre-allocated matrix `K` will be overwritten with
the kernel matrix.
"""
function kernelmatrix!(
    σ::Orientation,
    K::Matrix{Union{Missing, T}},
    κ::Kernel{T},
    X::AbstractMatrix{mT1},
    Y::AbstractMatrix{mT2}
) where
    {mT1 <: Union{Missing, T}} where
    {mT2 <: Union{Missing, T}} where
    {T <: AbstractFloat}

    # NOTE: for whatever reason, this gets inferred to ::Any ONLY in this
    # function. This causes the compiler to think that there is no method for
    # basematrix! because there is no basematrix!(..., f::Any, ...) method. This
    # can be fixed by inlining everything manually, by manually narrowing the
    # return type to basefunction(κ)::BaseFunction or by widening the type
    # signatures of basematrix!(..., f::Any, ...)
    f = basefunction(κ)

    basematrix!(σ, K, f, X, Y)
    kappamatrix!(κ, K)

    return K
end

function kernelmatrix(
    σ::Orientation,
    κ::Kernel{T},
    X::AbstractMatrix{Union{T, Missing}},
    symmetrize::Bool = true
) where {T<:AbstractFloat}

    K = allocate_basematrix(σ, X)
    kernelmatrix!(σ, K, κ, X, symmetrize)

    return K
end

function kernelmatrix(
    σ::Orientation,
    κ::Kernel,
    X::AbstractMatrix{mT1},
    Y::AbstractMatrix{mT2}
) where {mT1 <: Union{Missing, T}} where {mT2 <: Union{Missing, T}} where {T<:AbstractFloat}

    K = allocate_basematrix(σ, X, Y)
    kernelmatrix!(σ, K, κ, X, Y)

    return K
end