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

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

Creates a batch of variables.

# Arguments
- `variable_entries`: The list of variables for the batch create variable request.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: A collection of key and value pairs.
"""
batch_create_variable(variableEntries; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("BatchCreateVariable", Dict{String, Any}("variableEntries"=>variableEntries); aws_config=aws_config)
batch_create_variable(variableEntries, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("BatchCreateVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("variableEntries"=>variableEntries), params)); aws_config=aws_config)

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

Gets a batch of variables.

# Arguments
- `names`: The list of variable names to get.

"""
batch_get_variable(names; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("BatchGetVariable", Dict{String, Any}("names"=>names); aws_config=aws_config)
batch_get_variable(names, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("BatchGetVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("names"=>names), params)); aws_config=aws_config)

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

Cancels the specified batch prediction job.

# Arguments
- `job_id`: The ID of the batch prediction job to cancel.

"""
cancel_batch_prediction_job(jobId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CancelBatchPredictionJob", Dict{String, Any}("jobId"=>jobId); aws_config=aws_config)
cancel_batch_prediction_job(jobId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CancelBatchPredictionJob", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("jobId"=>jobId), params)); aws_config=aws_config)

"""
    create_batch_prediction_job(detector_name, event_type_name, iam_role_arn, input_path, job_id, output_path)
    create_batch_prediction_job(detector_name, event_type_name, iam_role_arn, input_path, job_id, output_path, params::Dict{String,<:Any})

Creates a batch prediction job.

# Arguments
- `detector_name`: The name of the detector.
- `event_type_name`: The name of the event type.
- `iam_role_arn`: The ARN of the IAM role to use for this job request.
- `input_path`: The Amazon S3 location of your training file.
- `job_id`: The ID of the batch prediction job.
- `output_path`: The Amazon S3 location of your output file.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"detectorVersion"`: The detector version.
- `"tags"`: A collection of key and value pairs.
"""
create_batch_prediction_job(detectorName, eventTypeName, iamRoleArn, inputPath, jobId, outputPath; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateBatchPredictionJob", Dict{String, Any}("detectorName"=>detectorName, "eventTypeName"=>eventTypeName, "iamRoleArn"=>iamRoleArn, "inputPath"=>inputPath, "jobId"=>jobId, "outputPath"=>outputPath); aws_config=aws_config)
create_batch_prediction_job(detectorName, eventTypeName, iamRoleArn, inputPath, jobId, outputPath, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateBatchPredictionJob", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorName"=>detectorName, "eventTypeName"=>eventTypeName, "iamRoleArn"=>iamRoleArn, "inputPath"=>inputPath, "jobId"=>jobId, "outputPath"=>outputPath), params)); aws_config=aws_config)

"""
    create_detector_version(detector_id, rules)
    create_detector_version(detector_id, rules, params::Dict{String,<:Any})

Creates a detector version. The detector version starts in a DRAFT status.

# Arguments
- `detector_id`: The ID of the detector under which you want to create a new version.
- `rules`: The rules to include in the detector version.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The description of the detector version.
- `"externalModelEndpoints"`: The Amazon Sagemaker model endpoints to include in the
  detector version.
- `"modelVersions"`: The model versions to include in the detector version.
- `"ruleExecutionMode"`: The rule execution mode for the rules included in the detector
  version. You can define and edit the rule mode at the detector version level, when it is in
  draft status. If you specify FIRST_MATCHED, Amazon Fraud Detector evaluates rules
  sequentially, first to last, stopping at the first matched rule. Amazon Fraud dectector
  then provides the outcomes for that single rule. If you specifiy ALL_MATCHED, Amazon Fraud
  Detector evaluates all rules and returns the outcomes for all matched rules.  The default
  behavior is FIRST_MATCHED.
- `"tags"`: A collection of key and value pairs.
"""
create_detector_version(detectorId, rules; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateDetectorVersion", Dict{String, Any}("detectorId"=>detectorId, "rules"=>rules); aws_config=aws_config)
create_detector_version(detectorId, rules, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateDetectorVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "rules"=>rules), params)); aws_config=aws_config)

"""
    create_model(event_type_name, model_id, model_type)
    create_model(event_type_name, model_id, model_type, params::Dict{String,<:Any})

Creates a model using the specified model type.

# Arguments
- `event_type_name`: The name of the event type.
- `model_id`: The model ID.
- `model_type`: The model type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The model description.
- `"tags"`: A collection of key and value pairs.
"""
create_model(eventTypeName, modelId, modelType; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateModel", Dict{String, Any}("eventTypeName"=>eventTypeName, "modelId"=>modelId, "modelType"=>modelType); aws_config=aws_config)
create_model(eventTypeName, modelId, modelType, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateModel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("eventTypeName"=>eventTypeName, "modelId"=>modelId, "modelType"=>modelType), params)); aws_config=aws_config)

"""
    create_model_version(model_id, model_type, training_data_schema, training_data_source)
    create_model_version(model_id, model_type, training_data_schema, training_data_source, params::Dict{String,<:Any})

Creates a version of the model using the specified model type and model id.

# Arguments
- `model_id`: The model ID.
- `model_type`: The model type.
- `training_data_schema`: The training data schema.
- `training_data_source`: The training data source location in Amazon S3.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"externalEventsDetail"`: Details for the external events data used for model version
  training. Required if trainingDataSource is EXTERNAL_EVENTS.
- `"tags"`: A collection of key and value pairs.
"""
create_model_version(modelId, modelType, trainingDataSchema, trainingDataSource; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateModelVersion", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "trainingDataSchema"=>trainingDataSchema, "trainingDataSource"=>trainingDataSource); aws_config=aws_config)
create_model_version(modelId, modelType, trainingDataSchema, trainingDataSource, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateModelVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "trainingDataSchema"=>trainingDataSchema, "trainingDataSource"=>trainingDataSource), params)); aws_config=aws_config)

"""
    create_rule(detector_id, expression, language, outcomes, rule_id)
    create_rule(detector_id, expression, language, outcomes, rule_id, params::Dict{String,<:Any})

Creates a rule for use with the specified detector.

# Arguments
- `detector_id`: The detector ID for the rule's parent detector.
- `expression`: The rule expression.
- `language`: The language of the rule.
- `outcomes`: The outcome or outcomes returned when the rule expression matches.
- `rule_id`: The rule ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The rule description.
- `"tags"`: A collection of key and value pairs.
"""
create_rule(detectorId, expression, language, outcomes, ruleId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateRule", Dict{String, Any}("detectorId"=>detectorId, "expression"=>expression, "language"=>language, "outcomes"=>outcomes, "ruleId"=>ruleId); aws_config=aws_config)
create_rule(detectorId, expression, language, outcomes, ruleId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateRule", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "expression"=>expression, "language"=>language, "outcomes"=>outcomes, "ruleId"=>ruleId), params)); aws_config=aws_config)

"""
    create_variable(data_source, data_type, default_value, name)
    create_variable(data_source, data_type, default_value, name, params::Dict{String,<:Any})

Creates a variable.

# Arguments
- `data_source`: The source of the data.
- `data_type`: The data type.
- `default_value`: The default value for the variable when no value is received.
- `name`: The name of the variable.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The description.
- `"tags"`: A collection of key and value pairs.
- `"variableType"`: The variable type. For more information see Variable types.  Valid
  Values: AUTH_CODE | AVS | BILLING_ADDRESS_L1 | BILLING_ADDRESS_L2 | BILLING_CITY |
  BILLING_COUNTRY | BILLING_NAME | BILLING_PHONE | BILLING_STATE | BILLING_ZIP | CARD_BIN |
  CATEGORICAL | CURRENCY_CODE | EMAIL_ADDRESS | FINGERPRINT | FRAUD_LABEL | FREE_FORM_TEXT |
  IP_ADDRESS | NUMERIC | ORDER_ID | PAYMENT_TYPE | PHONE_NUMBER | PRICE | PRODUCT_CATEGORY |
  SHIPPING_ADDRESS_L1 | SHIPPING_ADDRESS_L2 | SHIPPING_CITY | SHIPPING_COUNTRY |
  SHIPPING_NAME | SHIPPING_PHONE | SHIPPING_STATE | SHIPPING_ZIP | USERAGENT
"""
create_variable(dataSource, dataType, defaultValue, name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateVariable", Dict{String, Any}("dataSource"=>dataSource, "dataType"=>dataType, "defaultValue"=>defaultValue, "name"=>name); aws_config=aws_config)
create_variable(dataSource, dataType, defaultValue, name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("CreateVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("dataSource"=>dataSource, "dataType"=>dataType, "defaultValue"=>defaultValue, "name"=>name), params)); aws_config=aws_config)

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

Deletes a batch prediction job.

# Arguments
- `job_id`: The ID of the batch prediction job to delete.

"""
delete_batch_prediction_job(jobId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteBatchPredictionJob", Dict{String, Any}("jobId"=>jobId); aws_config=aws_config)
delete_batch_prediction_job(jobId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteBatchPredictionJob", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("jobId"=>jobId), params)); aws_config=aws_config)

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

Deletes the detector. Before deleting a detector, you must first delete all detector
versions and rule versions associated with the detector. When you delete a detector, Amazon
Fraud Detector permanently deletes the detector and the data is no longer stored in Amazon
Fraud Detector.

# Arguments
- `detector_id`: The ID of the detector to delete.

"""
delete_detector(detectorId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteDetector", Dict{String, Any}("detectorId"=>detectorId); aws_config=aws_config)
delete_detector(detectorId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteDetector", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId), params)); aws_config=aws_config)

"""
    delete_detector_version(detector_id, detector_version_id)
    delete_detector_version(detector_id, detector_version_id, params::Dict{String,<:Any})

Deletes the detector version. You cannot delete detector versions that are in ACTIVE
status. When you delete a detector version, Amazon Fraud Detector permanently deletes the
detector and the data is no longer stored in Amazon Fraud Detector.

# Arguments
- `detector_id`: The ID of the parent detector for the detector version to delete.
- `detector_version_id`: The ID of the detector version to delete.

"""
delete_detector_version(detectorId, detectorVersionId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteDetectorVersion", Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId); aws_config=aws_config)
delete_detector_version(detectorId, detectorVersionId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteDetectorVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId), params)); aws_config=aws_config)

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

Deletes an entity type. You cannot delete an entity type that is included in an event type.
When you delete an entity type, Amazon Fraud Detector permanently deletes that entity type
and the data is no longer stored in Amazon Fraud Detector.

# Arguments
- `name`: The name of the entity type to delete.

"""
delete_entity_type(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteEntityType", Dict{String, Any}("name"=>name); aws_config=aws_config)
delete_entity_type(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteEntityType", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

"""
    delete_event(event_id, event_type_name)
    delete_event(event_id, event_type_name, params::Dict{String,<:Any})

Deletes the specified event. When you delete an event, Amazon Fraud Detector permanently
deletes that event and the event data is no longer stored in Amazon Fraud Detector.

# Arguments
- `event_id`: The ID of the event to delete.
- `event_type_name`: The name of the event type.

"""
delete_event(eventId, eventTypeName; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteEvent", Dict{String, Any}("eventId"=>eventId, "eventTypeName"=>eventTypeName); aws_config=aws_config)
delete_event(eventId, eventTypeName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteEvent", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("eventId"=>eventId, "eventTypeName"=>eventTypeName), params)); aws_config=aws_config)

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

Deletes an event type. You cannot delete an event type that is used in a detector or a
model. When you delete an entity type, Amazon Fraud Detector permanently deletes that
entity type and the data is no longer stored in Amazon Fraud Detector.

# Arguments
- `name`: The name of the event type to delete.

"""
delete_event_type(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteEventType", Dict{String, Any}("name"=>name); aws_config=aws_config)
delete_event_type(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteEventType", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

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

Removes a SageMaker model from Amazon Fraud Detector. You can remove an Amazon SageMaker
model if it is not associated with a detector version. Removing a SageMaker model
disconnects it from Amazon Fraud Detector, but the model remains available in SageMaker.

# Arguments
- `model_endpoint`: The endpoint of the Amazon Sagemaker model to delete.

"""
delete_external_model(modelEndpoint; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteExternalModel", Dict{String, Any}("modelEndpoint"=>modelEndpoint); aws_config=aws_config)
delete_external_model(modelEndpoint, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteExternalModel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelEndpoint"=>modelEndpoint), params)); aws_config=aws_config)

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

Deletes a label. You cannot delete labels that are included in an event type in Amazon
Fraud Detector. You cannot delete a label assigned to an event ID. You must first delete
the relevant event ID. When you delete a label, Amazon Fraud Detector permanently deletes
that label and the data is no longer stored in Amazon Fraud Detector.

# Arguments
- `name`: The name of the label to delete.

"""
delete_label(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteLabel", Dict{String, Any}("name"=>name); aws_config=aws_config)
delete_label(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteLabel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

"""
    delete_model(model_id, model_type)
    delete_model(model_id, model_type, params::Dict{String,<:Any})

Deletes a model. You can delete models and model versions in Amazon Fraud Detector,
provided that they are not associated with a detector version.  When you delete a model,
Amazon Fraud Detector permanently deletes that model and the data is no longer stored in
Amazon Fraud Detector.

# Arguments
- `model_id`: The model ID of the model to delete.
- `model_type`: The model type of the model to delete.

"""
delete_model(modelId, modelType; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteModel", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType); aws_config=aws_config)
delete_model(modelId, modelType, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteModel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType), params)); aws_config=aws_config)

"""
    delete_model_version(model_id, model_type, model_version_number)
    delete_model_version(model_id, model_type, model_version_number, params::Dict{String,<:Any})

Deletes a model version. You can delete models and model versions in Amazon Fraud Detector,
provided that they are not associated with a detector version.  When you delete a model
version, Amazon Fraud Detector permanently deletes that model version and the data is no
longer stored in Amazon Fraud Detector.

# Arguments
- `model_id`: The model ID of the model version to delete.
- `model_type`: The model type of the model version to delete.
- `model_version_number`: The model version number of the model version to delete.

"""
delete_model_version(modelId, modelType, modelVersionNumber; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteModelVersion", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber); aws_config=aws_config)
delete_model_version(modelId, modelType, modelVersionNumber, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteModelVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber), params)); aws_config=aws_config)

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

Deletes an outcome. You cannot delete an outcome that is used in a rule version. When you
delete an outcome, Amazon Fraud Detector permanently deletes that outcome and the data is
no longer stored in Amazon Fraud Detector.

# Arguments
- `name`: The name of the outcome to delete.

"""
delete_outcome(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteOutcome", Dict{String, Any}("name"=>name); aws_config=aws_config)
delete_outcome(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteOutcome", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

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

Deletes the rule. You cannot delete a rule if it is used by an ACTIVE or INACTIVE detector
version. When you delete a rule, Amazon Fraud Detector permanently deletes that rule and
the data is no longer stored in Amazon Fraud Detector.

# Arguments
- `rule`:

"""
delete_rule(rule; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteRule", Dict{String, Any}("rule"=>rule); aws_config=aws_config)
delete_rule(rule, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteRule", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("rule"=>rule), params)); aws_config=aws_config)

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

Deletes a variable. You can't delete variables that are included in an event type in Amazon
Fraud Detector. Amazon Fraud Detector automatically deletes model output variables and
SageMaker model output variables when you delete the model. You can't delete these
variables manually. When you delete a variable, Amazon Fraud Detector permanently deletes
that variable and the data is no longer stored in Amazon Fraud Detector.

# Arguments
- `name`: The name of the variable to delete.

"""
delete_variable(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteVariable", Dict{String, Any}("name"=>name); aws_config=aws_config)
delete_variable(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DeleteVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

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

Gets all versions for a specified detector.

# Arguments
- `detector_id`: The detector ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return for the request.
- `"nextToken"`: The next token from the previous response.
"""
describe_detector(detectorId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DescribeDetector", Dict{String, Any}("detectorId"=>detectorId); aws_config=aws_config)
describe_detector(detectorId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DescribeDetector", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId), params)); aws_config=aws_config)

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

Gets all of the model versions for the specified model type or for the specified model type
and model ID. You can also get details for a single, specified model version.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of results to return.
- `"modelId"`: The model ID.
- `"modelType"`: The model type.
- `"modelVersionNumber"`: The model version number.
- `"nextToken"`: The next token from the previous results.
"""
describe_model_versions(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DescribeModelVersions"; aws_config=aws_config)
describe_model_versions(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("DescribeModelVersions", params; aws_config=aws_config)

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

Gets all batch prediction jobs or a specific job if you specify a job ID. This is a
paginated API. If you provide a null maxResults, this action retrieves a maximum of 50
records per page. If you provide a maxResults, the value must be between 1 and 50. To get
the next page results, provide the pagination token from the GetBatchPredictionJobsResponse
as part of your request. A null pagination token fetches the records from the beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"jobId"`: The batch prediction job for which to get the details.
- `"maxResults"`: The maximum number of objects to return for the request.
- `"nextToken"`: The next token from the previous request.
"""
get_batch_prediction_jobs(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetBatchPredictionJobs"; aws_config=aws_config)
get_batch_prediction_jobs(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetBatchPredictionJobs", params; aws_config=aws_config)

"""
    get_detector_version(detector_id, detector_version_id)
    get_detector_version(detector_id, detector_version_id, params::Dict{String,<:Any})

Gets a particular detector version.

# Arguments
- `detector_id`: The detector ID.
- `detector_version_id`: The detector version ID.

"""
get_detector_version(detectorId, detectorVersionId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetDetectorVersion", Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId); aws_config=aws_config)
get_detector_version(detectorId, detectorVersionId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetDetectorVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId), params)); aws_config=aws_config)

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

Gets all detectors or a single detector if a detectorId is specified. This is a paginated
API. If you provide a null maxResults, this action retrieves a maximum of 10 records per
page. If you provide a maxResults, the value must be between 5 and 10. To get the next page
results, provide the pagination token from the GetDetectorsResponse as part of your
request. A null pagination token fetches the records from the beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"detectorId"`: The detector ID.
- `"maxResults"`: The maximum number of objects to return for the request.
- `"nextToken"`: The next token for the subsequent request.
"""
get_detectors(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetDetectors"; aws_config=aws_config)
get_detectors(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetDetectors", params; aws_config=aws_config)

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

Gets all entity types or a specific entity type if a name is specified. This is a paginated
API. If you provide a null maxResults, this action retrieves a maximum of 10 records per
page. If you provide a maxResults, the value must be between 5 and 10. To get the next page
results, provide the pagination token from the GetEntityTypesResponse as part of your
request. A null pagination token fetches the records from the beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of objects to return for the request.
- `"name"`: The name.
- `"nextToken"`: The next token for the subsequent request.
"""
get_entity_types(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetEntityTypes"; aws_config=aws_config)
get_entity_types(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetEntityTypes", params; aws_config=aws_config)

"""
    get_event_prediction(detector_id, entities, event_id, event_timestamp, event_type_name, event_variables)
    get_event_prediction(detector_id, entities, event_id, event_timestamp, event_type_name, event_variables, params::Dict{String,<:Any})

Evaluates an event against a detector version. If a version ID is not provided, the
detector’s (ACTIVE) version is used.

# Arguments
- `detector_id`: The detector ID.
- `entities`: The entity type (associated with the detector's event type) and specific
  entity ID representing who performed the event. If an entity id is not available, use
  \"UNKNOWN.\"
- `event_id`: The unique ID used to identify the event.
- `event_timestamp`: Timestamp that defines when the event under evaluation occurred.
- `event_type_name`: The event type associated with the detector specified for the
  prediction.
- `event_variables`: Names of the event type's variables you defined in Amazon Fraud
  Detector to represent data elements and their corresponding values for the event you are
  sending for evaluation.    You must provide at least one eventVariable   If detectorVersion
  is associated with a modelVersion, you must provide at least one associated eventVariable
   To ensure highest possible fraud prediction and to simplify your data preparation, Amazon
  Fraud Detector will replace all missing variables or values as follows:  For Amazon Fraud
  Detector trained models:  If a null value is provided explicitly for a variable or if a
  variable is missing, model will replace the null value or the missing variable (no variable
  name in the eventVariables map) with calculated default mean/medians for numeric variables
  and with special values for categorical variables.  For External models ( for example,
  imported SageMaker):  If a null value is provided explicitly for a variable, the model and
  rules will use “null” as the value. If a variable is not provided (no variable name in
  the eventVariables map), model and rules will use the default value that is provided for
  the variable.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"detectorVersionId"`: The detector version ID.
- `"externalModelEndpointDataBlobs"`: The Amazon SageMaker model endpoint input data blobs.
"""
get_event_prediction(detectorId, entities, eventId, eventTimestamp, eventTypeName, eventVariables; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetEventPrediction", Dict{String, Any}("detectorId"=>detectorId, "entities"=>entities, "eventId"=>eventId, "eventTimestamp"=>eventTimestamp, "eventTypeName"=>eventTypeName, "eventVariables"=>eventVariables); aws_config=aws_config)
get_event_prediction(detectorId, entities, eventId, eventTimestamp, eventTypeName, eventVariables, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetEventPrediction", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "entities"=>entities, "eventId"=>eventId, "eventTimestamp"=>eventTimestamp, "eventTypeName"=>eventTypeName, "eventVariables"=>eventVariables), params)); aws_config=aws_config)

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

Gets all event types or a specific event type if name is provided. This is a paginated API.
If you provide a null maxResults, this action retrieves a maximum of 10 records per page.
If you provide a maxResults, the value must be between 5 and 10. To get the next page
results, provide the pagination token from the GetEventTypesResponse as part of your
request. A null pagination token fetches the records from the beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of objects to return for the request.
- `"name"`: The name.
- `"nextToken"`: The next token for the subsequent request.
"""
get_event_types(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetEventTypes"; aws_config=aws_config)
get_event_types(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetEventTypes", params; aws_config=aws_config)

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

Gets the details for one or more Amazon SageMaker models that have been imported into the
service. This is a paginated API. If you provide a null maxResults, this actions retrieves
a maximum of 10 records per page. If you provide a maxResults, the value must be between 5
and 10. To get the next page results, provide the pagination token from the
GetExternalModelsResult as part of your request. A null pagination token fetches the
records from the beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of objects to return for the request.
- `"modelEndpoint"`: The Amazon SageMaker model endpoint.
- `"nextToken"`: The next page token for the request.
"""
get_external_models(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetExternalModels"; aws_config=aws_config)
get_external_models(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetExternalModels", params; aws_config=aws_config)

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

Gets the encryption key if a Key Management Service (KMS) customer master key (CMK) has
been specified to be used to encrypt content in Amazon Fraud Detector.

"""
get_kmsencryption_key(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetKMSEncryptionKey"; aws_config=aws_config)
get_kmsencryption_key(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetKMSEncryptionKey", params; aws_config=aws_config)

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

Gets all labels or a specific label if name is provided. This is a paginated API. If you
provide a null maxResults, this action retrieves a maximum of 50 records per page. If you
provide a maxResults, the value must be between 10 and 50. To get the next page results,
provide the pagination token from the GetGetLabelsResponse as part of your request. A null
pagination token fetches the records from the beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of objects to return for the request.
- `"name"`: The name of the label or labels to get.
- `"nextToken"`: The next token for the subsequent request.
"""
get_labels(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetLabels"; aws_config=aws_config)
get_labels(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetLabels", params; aws_config=aws_config)

"""
    get_model_version(model_id, model_type, model_version_number)
    get_model_version(model_id, model_type, model_version_number, params::Dict{String,<:Any})

Gets the details of the specified model version.

# Arguments
- `model_id`: The model ID.
- `model_type`: The model type.
- `model_version_number`: The model version number.

"""
get_model_version(modelId, modelType, modelVersionNumber; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetModelVersion", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber); aws_config=aws_config)
get_model_version(modelId, modelType, modelVersionNumber, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetModelVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber), params)); aws_config=aws_config)

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

Gets one or more models. Gets all models for the AWS account if no model type and no model
id provided. Gets all models for the AWS account and model type, if the model type is
specified but model id is not provided. Gets a specific model if (model type, model id)
tuple is specified.  This is a paginated API. If you provide a null maxResults, this action
retrieves a maximum of 10 records per page. If you provide a maxResults, the value must be
between 1 and 10. To get the next page results, provide the pagination token from the
response as part of your request. A null pagination token fetches the records from the
beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of objects to return for the request.
- `"modelId"`: The model ID.
- `"modelType"`: The model type.
- `"nextToken"`: The next token for the subsequent request.
"""
get_models(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetModels"; aws_config=aws_config)
get_models(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetModels", params; aws_config=aws_config)

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

Gets one or more outcomes. This is a paginated API. If you provide a null maxResults, this
actions retrieves a maximum of 100 records per page. If you provide a maxResults, the value
must be between 50 and 100. To get the next page results, provide the pagination token from
the GetOutcomesResult as part of your request. A null pagination token fetches the records
from the beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of objects to return for the request.
- `"name"`: The name of the outcome or outcomes to get.
- `"nextToken"`: The next page token for the request.
"""
get_outcomes(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetOutcomes"; aws_config=aws_config)
get_outcomes(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetOutcomes", params; aws_config=aws_config)

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

Get all rules for a detector (paginated) if ruleId and ruleVersion are not specified. Gets
all rules for the detector and the ruleId if present (paginated). Gets a specific rule if
both the ruleId and the ruleVersion are specified. This is a paginated API. Providing null
maxResults results in retrieving maximum of 100 records per page. If you provide maxResults
the value must be between 50 and 100. To get the next page result, a provide a pagination
token from GetRulesResult as part of your request. Null pagination token fetches the
records from the beginning.

# Arguments
- `detector_id`: The detector ID.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of rules to return for the request.
- `"nextToken"`: The next page token.
- `"ruleId"`: The rule ID.
- `"ruleVersion"`: The rule version.
"""
get_rules(detectorId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetRules", Dict{String, Any}("detectorId"=>detectorId); aws_config=aws_config)
get_rules(detectorId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetRules", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId), params)); aws_config=aws_config)

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

Gets all of the variables or the specific variable. This is a paginated API. Providing null
maxSizePerPage results in retrieving maximum of 100 records per page. If you provide
maxSizePerPage the value must be between 50 and 100. To get the next page result, a provide
a pagination token from GetVariablesResult as part of your request. Null pagination token
fetches the records from the beginning.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The max size per page determined for the get variable request.
- `"name"`: The name of the variable.
- `"nextToken"`: The next page token of the get variable request.
"""
get_variables(; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetVariables"; aws_config=aws_config)
get_variables(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("GetVariables", params; aws_config=aws_config)

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

Lists all tags associated with the resource. This is a paginated API. To get the next page
results, provide the pagination token from the response as part of your request. A null
pagination token fetches the records from the beginning.

# Arguments
- `resource_arn`: The ARN that specifies the resource whose tags you want to list.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`: The maximum number of objects to return for the request.
- `"nextToken"`: The next token from the previous results.
"""
list_tags_for_resource(resourceARN; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("ListTagsForResource", Dict{String, Any}("resourceARN"=>resourceARN); aws_config=aws_config)
list_tags_for_resource(resourceARN, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("ListTagsForResource", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceARN"=>resourceARN), params)); aws_config=aws_config)

"""
    put_detector(detector_id, event_type_name)
    put_detector(detector_id, event_type_name, params::Dict{String,<:Any})

Creates or updates a detector.

# Arguments
- `detector_id`: The detector ID.
- `event_type_name`: The name of the event type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The description of the detector.
- `"tags"`: A collection of key and value pairs.
"""
put_detector(detectorId, eventTypeName; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutDetector", Dict{String, Any}("detectorId"=>detectorId, "eventTypeName"=>eventTypeName); aws_config=aws_config)
put_detector(detectorId, eventTypeName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutDetector", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "eventTypeName"=>eventTypeName), params)); aws_config=aws_config)

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

Creates or updates an entity type. An entity represents who is performing the event. As
part of a fraud prediction, you pass the entity ID to indicate the specific entity who
performed the event. An entity type classifies the entity. Example classifications include
customer, merchant, or account.

# Arguments
- `name`: The name of the entity type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The description.
- `"tags"`: A collection of key and value pairs.
"""
put_entity_type(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutEntityType", Dict{String, Any}("name"=>name); aws_config=aws_config)
put_entity_type(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutEntityType", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

"""
    put_event_type(entity_types, event_variables, name)
    put_event_type(entity_types, event_variables, name, params::Dict{String,<:Any})

Creates or updates an event type. An event is a business activity that is evaluated for
fraud risk. With Amazon Fraud Detector, you generate fraud predictions for events. An event
type defines the structure for an event sent to Amazon Fraud Detector. This includes the
variables sent as part of the event, the entity performing the event (such as a customer),
and the labels that classify the event. Example event types include online payment
transactions, account registrations, and authentications.

# Arguments
- `entity_types`: The entity type for the event type. Example entity types: customer,
  merchant, account.
- `event_variables`: The event type variables.
- `name`: The name.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The description of the event type.
- `"labels"`: The event type labels.
- `"tags"`: A collection of key and value pairs.
"""
put_event_type(entityTypes, eventVariables, name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutEventType", Dict{String, Any}("entityTypes"=>entityTypes, "eventVariables"=>eventVariables, "name"=>name); aws_config=aws_config)
put_event_type(entityTypes, eventVariables, name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutEventType", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("entityTypes"=>entityTypes, "eventVariables"=>eventVariables, "name"=>name), params)); aws_config=aws_config)

"""
    put_external_model(input_configuration, invoke_model_endpoint_role_arn, model_endpoint, model_endpoint_status, model_source, output_configuration)
    put_external_model(input_configuration, invoke_model_endpoint_role_arn, model_endpoint, model_endpoint_status, model_source, output_configuration, params::Dict{String,<:Any})

Creates or updates an Amazon SageMaker model endpoint. You can also use this action to
update the configuration of the model endpoint, including the IAM role and/or the mapped
variables.

# Arguments
- `input_configuration`: The model endpoint input configuration.
- `invoke_model_endpoint_role_arn`: The IAM role used to invoke the model endpoint.
- `model_endpoint`: The model endpoints name.
- `model_endpoint_status`: The model endpoint’s status in Amazon Fraud Detector.
- `model_source`: The source of the model.
- `output_configuration`: The model endpoint output configuration.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"tags"`: A collection of key and value pairs.
"""
put_external_model(inputConfiguration, invokeModelEndpointRoleArn, modelEndpoint, modelEndpointStatus, modelSource, outputConfiguration; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutExternalModel", Dict{String, Any}("inputConfiguration"=>inputConfiguration, "invokeModelEndpointRoleArn"=>invokeModelEndpointRoleArn, "modelEndpoint"=>modelEndpoint, "modelEndpointStatus"=>modelEndpointStatus, "modelSource"=>modelSource, "outputConfiguration"=>outputConfiguration); aws_config=aws_config)
put_external_model(inputConfiguration, invokeModelEndpointRoleArn, modelEndpoint, modelEndpointStatus, modelSource, outputConfiguration, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutExternalModel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("inputConfiguration"=>inputConfiguration, "invokeModelEndpointRoleArn"=>invokeModelEndpointRoleArn, "modelEndpoint"=>modelEndpoint, "modelEndpointStatus"=>modelEndpointStatus, "modelSource"=>modelSource, "outputConfiguration"=>outputConfiguration), params)); aws_config=aws_config)

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

Specifies the Key Management Service (KMS) customer master key (CMK) to be used to encrypt
content in Amazon Fraud Detector.

# Arguments
- `kms_encryption_key_arn`: The KMS encryption key ARN.

"""
put_kmsencryption_key(kmsEncryptionKeyArn; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutKMSEncryptionKey", Dict{String, Any}("kmsEncryptionKeyArn"=>kmsEncryptionKeyArn); aws_config=aws_config)
put_kmsencryption_key(kmsEncryptionKeyArn, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutKMSEncryptionKey", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("kmsEncryptionKeyArn"=>kmsEncryptionKeyArn), params)); aws_config=aws_config)

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

Creates or updates label. A label classifies an event as fraudulent or legitimate. Labels
are associated with event types and used to train supervised machine learning models in
Amazon Fraud Detector.

# Arguments
- `name`: The label name.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The label description.
- `"tags"`:
"""
put_label(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutLabel", Dict{String, Any}("name"=>name); aws_config=aws_config)
put_label(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutLabel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

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

Creates or updates an outcome.

# Arguments
- `name`: The name of the outcome.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The outcome description.
- `"tags"`: A collection of key and value pairs.
"""
put_outcome(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutOutcome", Dict{String, Any}("name"=>name); aws_config=aws_config)
put_outcome(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("PutOutcome", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)

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

Assigns tags to a resource.

# Arguments
- `resource_arn`: The resource ARN.
- `tags`: The tags to assign to the resource.

"""
tag_resource(resourceARN, tags; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("TagResource", Dict{String, Any}("resourceARN"=>resourceARN, "tags"=>tags); aws_config=aws_config)
tag_resource(resourceARN, tags, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("TagResource", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceARN"=>resourceARN, "tags"=>tags), params)); aws_config=aws_config)

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

Removes tags from a resource.

# Arguments
- `resource_arn`: The ARN of the resource from which to remove the tag.
- `tag_keys`: The resource ARN.

"""
untag_resource(resourceARN, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UntagResource", Dict{String, Any}("resourceARN"=>resourceARN, "tagKeys"=>tagKeys); aws_config=aws_config)
untag_resource(resourceARN, tagKeys, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UntagResource", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceARN"=>resourceARN, "tagKeys"=>tagKeys), params)); aws_config=aws_config)

"""
    update_detector_version(detector_id, detector_version_id, external_model_endpoints, rules)
    update_detector_version(detector_id, detector_version_id, external_model_endpoints, rules, params::Dict{String,<:Any})

 Updates a detector version. The detector version attributes that you can update include
models, external model endpoints, rules, rule execution mode, and description. You can only
update a DRAFT detector version.

# Arguments
- `detector_id`: The parent detector ID for the detector version you want to update.
- `detector_version_id`: The detector version ID.
- `external_model_endpoints`: The Amazon SageMaker model endpoints to include in the
  detector version.
- `rules`: The rules to include in the detector version.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The detector version description.
- `"modelVersions"`: The model versions to include in the detector version.
- `"ruleExecutionMode"`: The rule execution mode to add to the detector. If you specify
  FIRST_MATCHED, Amazon Fraud Detector evaluates rules sequentially, first to last, stopping
  at the first matched rule. Amazon Fraud dectector then provides the outcomes for that
  single rule. If you specifiy ALL_MATCHED, Amazon Fraud Detector evaluates all rules and
  returns the outcomes for all matched rules. You can define and edit the rule mode at the
  detector version level, when it is in draft status. The default behavior is FIRST_MATCHED.
"""
update_detector_version(detectorId, detectorVersionId, externalModelEndpoints, rules; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersion", Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId, "externalModelEndpoints"=>externalModelEndpoints, "rules"=>rules); aws_config=aws_config)
update_detector_version(detectorId, detectorVersionId, externalModelEndpoints, rules, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId, "externalModelEndpoints"=>externalModelEndpoints, "rules"=>rules), params)); aws_config=aws_config)

"""
    update_detector_version_metadata(description, detector_id, detector_version_id)
    update_detector_version_metadata(description, detector_id, detector_version_id, params::Dict{String,<:Any})

Updates the detector version's description. You can update the metadata for any detector
version (DRAFT, ACTIVE, or INACTIVE).

# Arguments
- `description`: The description.
- `detector_id`: The detector ID.
- `detector_version_id`: The detector version ID.

"""
update_detector_version_metadata(description, detectorId, detectorVersionId; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersionMetadata", Dict{String, Any}("description"=>description, "detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId); aws_config=aws_config)
update_detector_version_metadata(description, detectorId, detectorVersionId, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersionMetadata", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("description"=>description, "detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId), params)); aws_config=aws_config)

"""
    update_detector_version_status(detector_id, detector_version_id, status)
    update_detector_version_status(detector_id, detector_version_id, status, params::Dict{String,<:Any})

Updates the detector version’s status. You can perform the following promotions or
demotions using UpdateDetectorVersionStatus: DRAFT to ACTIVE, ACTIVE to INACTIVE, and
INACTIVE to ACTIVE.

# Arguments
- `detector_id`: The detector ID.
- `detector_version_id`: The detector version ID.
- `status`: The new status.

"""
update_detector_version_status(detectorId, detectorVersionId, status; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersionStatus", Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId, "status"=>status); aws_config=aws_config)
update_detector_version_status(detectorId, detectorVersionId, status, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersionStatus", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId, "status"=>status), params)); aws_config=aws_config)

"""
    update_model(model_id, model_type)
    update_model(model_id, model_type, params::Dict{String,<:Any})

Updates a model. You can update the description attribute using this action.

# Arguments
- `model_id`: The model ID.
- `model_type`: The model type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The new model description.
"""
update_model(modelId, modelType; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateModel", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType); aws_config=aws_config)
update_model(modelId, modelType, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateModel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType), params)); aws_config=aws_config)

"""
    update_model_version(major_version_number, model_id, model_type)
    update_model_version(major_version_number, model_id, model_type, params::Dict{String,<:Any})

Updates a model version. Updating a model version retrains an existing model version using
updated training data and produces a new minor version of the model. You can update the
training data set location and data access role attributes using this action. This action
creates and trains a new minor version of the model, for example version 1.01, 1.02, 1.03.

# Arguments
- `major_version_number`: The major version number.
- `model_id`: The model ID.
- `model_type`: The model type.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"externalEventsDetail"`: The event details.
- `"tags"`: A collection of key and value pairs.
"""
update_model_version(majorVersionNumber, modelId, modelType; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateModelVersion", Dict{String, Any}("majorVersionNumber"=>majorVersionNumber, "modelId"=>modelId, "modelType"=>modelType); aws_config=aws_config)
update_model_version(majorVersionNumber, modelId, modelType, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateModelVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("majorVersionNumber"=>majorVersionNumber, "modelId"=>modelId, "modelType"=>modelType), params)); aws_config=aws_config)

"""
    update_model_version_status(model_id, model_type, model_version_number, status)
    update_model_version_status(model_id, model_type, model_version_number, status, params::Dict{String,<:Any})

Updates the status of a model version. You can perform the following status updates:
Change the TRAINING_COMPLETE status to ACTIVE.   Change ACTIVEto INACTIVE.

# Arguments
- `model_id`: The model ID of the model version to update.
- `model_type`: The model type.
- `model_version_number`: The model version number.
- `status`: The model version status.

"""
update_model_version_status(modelId, modelType, modelVersionNumber, status; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateModelVersionStatus", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber, "status"=>status); aws_config=aws_config)
update_model_version_status(modelId, modelType, modelVersionNumber, status, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateModelVersionStatus", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber, "status"=>status), params)); aws_config=aws_config)

"""
    update_rule_metadata(description, rule)
    update_rule_metadata(description, rule, params::Dict{String,<:Any})

Updates a rule's metadata. The description attribute can be updated.

# Arguments
- `description`: The rule description.
- `rule`: The rule to update.

"""
update_rule_metadata(description, rule; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateRuleMetadata", Dict{String, Any}("description"=>description, "rule"=>rule); aws_config=aws_config)
update_rule_metadata(description, rule, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateRuleMetadata", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("description"=>description, "rule"=>rule), params)); aws_config=aws_config)

"""
    update_rule_version(expression, language, outcomes, rule)
    update_rule_version(expression, language, outcomes, rule, params::Dict{String,<:Any})

Updates a rule version resulting in a new rule version. Updates a rule version resulting in
a new rule version (version 1, 2, 3 ...).

# Arguments
- `expression`: The rule expression.
- `language`: The language.
- `outcomes`: The outcomes.
- `rule`: The rule to update.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`: The description.
- `"tags"`: The tags to assign to the rule version.
"""
update_rule_version(expression, language, outcomes, rule; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateRuleVersion", Dict{String, Any}("expression"=>expression, "language"=>language, "outcomes"=>outcomes, "rule"=>rule); aws_config=aws_config)
update_rule_version(expression, language, outcomes, rule, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateRuleVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("expression"=>expression, "language"=>language, "outcomes"=>outcomes, "rule"=>rule), params)); aws_config=aws_config)

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

Updates a variable.

# Arguments
- `name`: The name of the variable.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"defaultValue"`: The new default value of the variable.
- `"description"`: The new description.
- `"variableType"`: The variable type. For more information see Variable types.
"""
update_variable(name; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateVariable", Dict{String, Any}("name"=>name); aws_config=aws_config)
update_variable(name, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = frauddetector("UpdateVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), params)); aws_config=aws_config)


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

@doc raw"""NetworkPolicyEgressRule describes a particular set of traffic that is allowed out of pods matched by a NetworkPolicySpec's podSelector. The traffic must match both ports and to. This type is beta-level in 1.8

    IoK8sApiNetworkingV1NetworkPolicyEgressRule(;
        ports=nothing,
        to=nothing,
    )

    - ports::Vector{IoK8sApiNetworkingV1NetworkPolicyPort} : List of destination ports for outgoing traffic. Each item in this list is combined using a logical OR. If this field is empty or missing, this rule matches all ports (traffic not restricted by port). If this field is present and contains at least one item, then this rule allows traffic only if the traffic matches at least one port in the list.
    - to::Vector{IoK8sApiNetworkingV1NetworkPolicyPeer} : List of destinations for outgoing traffic of pods selected for this rule. Items in this list are combined using a logical OR operation. If this field is empty or missing, this rule matches all destinations (traffic not restricted by destination). If this field is present and contains at least one item, this rule allows traffic only if the traffic matches at least one item in the to list.
"""
mutable struct IoK8sApiNetworkingV1NetworkPolicyEgressRule <: SwaggerModel
    ports::Any # spec type: Union{ Nothing, Vector{IoK8sApiNetworkingV1NetworkPolicyPort} } # spec name: ports
    to::Any # spec type: Union{ Nothing, Vector{IoK8sApiNetworkingV1NetworkPolicyPeer} } # spec name: to

    function IoK8sApiNetworkingV1NetworkPolicyEgressRule(;ports=nothing, to=nothing)
        o = new()
        validate_property(IoK8sApiNetworkingV1NetworkPolicyEgressRule, Symbol("ports"), ports)
        setfield!(o, Symbol("ports"), ports)
        validate_property(IoK8sApiNetworkingV1NetworkPolicyEgressRule, Symbol("to"), to)
        setfield!(o, Symbol("to"), to)
        o
    end
end # type IoK8sApiNetworkingV1NetworkPolicyEgressRule

const _property_map_IoK8sApiNetworkingV1NetworkPolicyEgressRule = Dict{Symbol,Symbol}(Symbol("ports")=>Symbol("ports"), Symbol("to")=>Symbol("to"))
const _property_types_IoK8sApiNetworkingV1NetworkPolicyEgressRule = Dict{Symbol,String}(Symbol("ports")=>"Vector{IoK8sApiNetworkingV1NetworkPolicyPort}", Symbol("to")=>"Vector{IoK8sApiNetworkingV1NetworkPolicyPeer}")
Base.propertynames(::Type{ IoK8sApiNetworkingV1NetworkPolicyEgressRule }) = collect(keys(_property_map_IoK8sApiNetworkingV1NetworkPolicyEgressRule))
Swagger.property_type(::Type{ IoK8sApiNetworkingV1NetworkPolicyEgressRule }, name::Symbol) = Union{Nothing,eval(Base.Meta.parse(_property_types_IoK8sApiNetworkingV1NetworkPolicyEgressRule[name]))}
Swagger.field_name(::Type{ IoK8sApiNetworkingV1NetworkPolicyEgressRule }, property_name::Symbol) =  _property_map_IoK8sApiNetworkingV1NetworkPolicyEgressRule[property_name]

function check_required(o::IoK8sApiNetworkingV1NetworkPolicyEgressRule)
    true
end

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

ext: jl


text:
function calculate_overlap(
    dataset::DataSet{T, I},
    volumes::Array{IntegrationVolume{T, I, V}, 1},
    integralestimates::IntermediateResults)::Array{T, 2} where{T<:AbstractFloat, I<:Integer, V<:SpatialVolume}

    M = length(integralestimates)

    overlap = zeros(T, M, M)

    sortedsets = SortedSet.([volumes[integralestimates.volumeID[i]].pointcloud.pointIDs for i = 1:M])

    idx = workpart(1:M, ParallelProcessingTools.workers(), ParallelProcessingTools.myid())
    @mt for i in workpart(idx, mt_nthreads(), threadid())
        for j = 1:M
            intersectpts = intersect(sortedsets[i], sortedsets[j])
            unionpts = union(sortedsets[i], sortedsets[j])

            overlap[i, j] = sum(dataset.weights[collect(intersectpts)]) / sum(dataset.weights[collect(unionpts)])
        end
    end
    overlap
end

function pdf_gauss(Z::Float64, μ::Float64,  σ_sq::Float64)::Float64
    return 1.0 / sqrt(2 * pi * σ_sq) * exp(-0.5 * (Z - μ)^2 / σ_sq)
end

function binomial_p_estimate_wald(n_total, n_success, nsigmas = 1)
    p_hat = n_success / n_total
    @assert p_hat >= 0 && p_hat <= 1
    @assert n_total > 0 && n_success > 0
    p_err = nsigmas * sqrt(p_hat * (1 - p_hat) / n_total)
end

function binomial_p_estimate_wilson(n_total, n_success, nsigmas = 1)
    n = n_total
    n_S = n_success
    n_F = n_total - n_S
    z = nsigmas
    z2 = z^2

    p_val = (n_S + z2/2) / (n + z2)

    p_err = z / (n + z2) * sqrt(n_S * n_F / n + z2 / 4)
end

function calculateuncertainty(dataset::DataSet{T, I}, volume::IntegrationVolume{T, I}, determinant::T, integral::T) where {T<:AbstractFloat, I<:Integer}

    #resorting the samples to undo the reordering of the space partitioning tree
    reorderscheme = sortperm(dataset.sortids[volume.pointcloud.pointIDs], rev = true)
    original_ordered_sample_ids = volume.pointcloud.pointIDs[reorderscheme]

    vol_samples = dataset.data[:, original_ordered_sample_ids]
    vol_weights = dataset.weights[original_ordered_sample_ids]

    x_min = 1.0 / dataset.N
    x_max = 1.0

    vol_weight = sum(vol_weights)
    total_weight = sum(dataset.weights)
    r = vol_weight / total_weight
    y_r = (x::Float64) -> Float64(x_min + (x_max - x_min) * x)

    ess = BAT.effective_sample_size(vol_samples, vol_weights)
    ess_total = BAT.effective_sample_size(dataset.data[:, dataset.sortids], dataset.weights[dataset.sortids])

    f = 1 ./ exp.(dataset.logprob[volume.pointcloud.pointIDs])

    μ_Z = mean(f)
    @assert ess>0

    σ_μZ_sq = var(f) / ess

    f_max = maximum(f)
    f_min = minimum(f)

    y = (x::Float64) -> Float64(f_min + (f_max - f_min) * x)

    integrand1(x) = pdf_gauss(y(x), μ_Z, σ_μZ_sq) / y(x)^2 * (f_max - f_min)
    integrand2(x) = pdf_gauss(y(x), μ_Z, σ_μZ_sq) / y(x) * (f_max - f_min)

    integral1 = QuadGK.quadgk(integrand1,0,1, rtol=0.001)[1]
    integral2 = QuadGK.quadgk(integrand2,0,1, rtol = 0.001)[1]

    uncertainty_Z = (integral1 - integral2^2) * volume.volume / r / determinant
    #set uncertainty to 0 if it is negative (numerical error)
    if uncertainty_Z < 0
        uncertainty_Z = 0
    else
        uncertainty_Z = sqrt(uncertainty_Z)
    end

    scaling_factor = ess / vol_weight
    scaling_factor_total = ess_total / total_weight

    uncertainty_r = binomial_p_estimate_wald(scaling_factor_total * total_weight, scaling_factor * vol_weight)
    uncertainty_r *= integral / r #error propagation

    uncertainty_tot = sqrt(uncertainty_Z^2 + uncertainty_r^2)

    return uncertainty_r, uncertainty_Z, uncertainty_tot, f_min, f_max, μ_Z, σ_μZ_sq, integral1, integral2, ess
end


text:
# Substitution Matrices
# ---------------------

"""
Supertype of substitution matrix.

The required method:

    * `Base.getindex(submat, x, y) = <substitution score/cost from x to y>`
"""
abstract AbstractSubstitutionMatrix{T<:Real}

"""
Substitution matrix.
"""
type SubstitutionMatrix{T} <: AbstractSubstitutionMatrix{T}
    submat::Matrix{T}
end

Base.getindex(m::SubstitutionMatrix, x, y) = m.submat[convert(UInt8, x)+1,convert(UInt8, y)+1]
Base.setindex!(m::SubstitutionMatrix, v, x, y) = m.submat[convert(UInt8, x)+1,convert(UInt8, y)+1] = v

# Score Models
# ------------

"""
Supertype of score model.

Every score model is a problem of finding the maximum score and its alignment.
"""
abstract AbstractScoreModel{T<:Real}

"""
Affine gap scoring model.

The gap penalty of length `k` is `gap_open_penalty + gap_extend_penalty * k`.

Fields:

    * `submat`: a substitution matrix
    * `gap_open_penalty`: a penalty of opening a new gap
    * `gap_extend_penalty`: a penalty of extending a gap
"""
type AffineGapScoreModel{T} <: AbstractScoreModel{T}
    submat::AbstractSubstitutionMatrix{T}
    gap_open_penalty::T
    gap_extend_penalty::T
end

function AffineGapScoreModel{T}(submat::AbstractSubstitutionMatrix{T},
                                gap_open_penalty, gap_extend_penalty)
    return AffineGapScoreModel{T}(submat, T(gap_open_penalty), T(gap_extend_penalty))
end

function AffineGapScoreModel{T}(submat::AbstractSubstitutionMatrix{T};
                                gap_open_penalty=nothing, gap_extend_penalty=nothing)
    if gap_open_penalty === nothing || gap_extend_penalty === nothing
        error("both gap_open_penalty and gap_extend_penalty should be set")
    end
    return AffineGapScoreModel(submat, gap_open_penalty, gap_extend_penalty)
end

function AffineGapScoreModel{T}(submat::AbstractMatrix{T};
                                gap_open_penalty=nothing, gap_extend_penalty=nothing)
    if gap_open_penalty === nothing || gap_extend_penalty === nothing
        error("both gap_open_penalty and gap_extend_penalty should be set")
    end
    return AffineGapScoreModel(SubstitutionMatrix(submat), gap_open_penalty, gap_extend_penalty)
end

# Cost Models
# -----------

immutable UnitSubstitutionCost{T} <: AbstractSubstitutionMatrix{T} end
Base.getindex{T}(::UnitSubstitutionCost{T}, x, y) = ifelse(x == y, T(0), T(1))

"""
Supertype of cost model.

Every cost model is a problem of finding the minimum cost and its alignment.
"""
abstract AbstractCostModel{T}

"""
Cost model.

Fields:

    * `submat`: a substitution matrix
    * `insertion_cost`: a cost of inserting a character into the first sequence
    * `deletion_cost`: a cost of deleting a character from the first sequence
"""
type CostModel{T} <: AbstractCostModel{T}
    submat::AbstractSubstitutionMatrix{T}
    insertion_cost::T
    deletion_cost::T
end

function CostModel{T}(submat::AbstractSubstitutionMatrix{T},
                      insertion_cost, deletion_cost)
    return CostModel{T}(submat, insertion_cost, deletion_cost)
end

function CostModel{T}(submat::AbstractSubstitutionMatrix{T};
                      insertion_cost=nothing, deletion_cost=nothing)
    if insertion_cost === nothing || deletion_cost === nothing
        error("both insertion_cost and deletion_cost should be set")
    end
    return CostModel(submat, insertion_cost, deletion_cost)
end

function CostModel{T}(submat::AbstractMatrix{T};
                      insertion_cost=nothing, deletion_cost=nothing)
    if insertion_cost === nothing || deletion_cost === nothing
        error("both insertion_cost and deletion_cost should be set")
    end
    return CostModel(SubstitutionMatrix(submat), insertion_cost, deletion_cost)
end


text:
function perf_lucompletepivCopy!(A)
    n = size(A, 1)
    rowpiv=zeros(Int, n-1)
    colpiv=zeros(Int, n-1)
    for k = 1:n-1
        As = abs.(A[k:n, k:n])
        μ, λ = argmax(A).I
        μ += k-1; λ += k-1
        rowpiv[k] = μ
        A[[k,μ], 1:n] = A[[μ,k], 1:n]
        colpiv[k] = λ
        A[1:n, [k,λ]] = A[1:n, [λ,k]]
        if A[k,k] ≠ 0
            ρ = k+1:n
            A[ρ, k] = A[ρ, k]/A[k, k]
            A[ρ, ρ] = A[ρ, ρ] - A[ρ, k:k] * A[k:k, ρ]
        end
    end
    return (A, rowpiv, colpiv)
end

function perf_lucompletepivSub!(A)
    n = size(A, 1)
    rowpiv=zeros(Int, n-1)
    colpiv=zeros(Int, n-1)
    for k = 1:n-1
        As = abs.(view(A, k:n, k:n))
        μ, λ = argmax(A).I
        μ += k-1; λ += k-1
        rowpiv[k] = μ
        A[[k,μ], 1:n] = view(A, [μ,k], 1:n)
        colpiv[k] = λ
        A[1:n, [k,λ]] = view(A, 1:n, [λ,k])
        if A[k,k] ≠ 0
            ρ = k+1:n
            A[ρ, k] = view(A, ρ, k)/A[k, k]
            A[ρ, ρ] = view(A, ρ, ρ) - view(A, ρ, k:k) * view(A, k:k, ρ)
        end
    end
    return (A, rowpiv, colpiv)
end

function perf_gramschmidt!(U)
    m = size(U, 2)
    @inbounds for k = 1:m
        uk = view(U,:,k)
        for j = 1:k-1
            uj = view(U,:,j)
            uk .-= (uj ⋅ uk) .* uj
        end
        uk ./= norm(uk)
    end
end


text:
module TransitionParsing

export
    ArcEager, ArcStandard, ArcHybrid, ArcSwift, ListBasedNonProjective,

    Oracle,
    static_oracle, dynamic_oracle, static_oracle_prefer_shift,
    typed, untyped,

    AlwaysExplore, NeverExplore, ExplorationPolicy,

    initconfig, isfinal, possible_transitions, transition_space,
    stacktoken, buffertoken

import Base.reduce

import Random.AbstractRNG
import Random.GLOBAL_RNG

import ..Token, ..DependencyTree, ..deptree, ..ROOT, ..deps, ..token,
    ..has_arc, ..has_head, ..is_projective, ..leftdeps, ..rightdeps,
    ..NonProjectiveGraphError

"""
    untyped(token)

Create an arc without a dependency label.
"""
untyped(token) = ()

"""
    typed(token)

Create an arc with a labeled dependency relation.
"""
typed(token) = (token.label,)

abstract type AbstractTransitionSystem end

include("systems/common.jl")
include("systems/arc_standard.jl")
include("systems/arc_eager.jl")
include("systems/arc_hybrid.jl")
include("systems/arc_swift.jl")
include("systems/listbased.jl")

include("oracles.jl")

end # module


text:
"""
A generic file logger for logging to files. Flushes the necessary output stream after each write (i.e. after each logging event) by default and closes the files on finalizing. Opened files are by default appended to. Given `append = false`, they will be overwritten.

    FileLogger(logPaths = Dict(Info => "default.log"); flush = true, append = true)

Logs logging events with LogLevel greater than or equal to `Info` to "default.log", should no `logPaths` be given. In case two LogLevels are present, e.g. `Info` and `Error`, all logging events from `Info` up to (but excluding) `Error` will be logged to the file given by `Info`. `Error` and above will be logged to the file given by `Error`. It is possible to "clamp" logging events, by providing an upper bound that's logging to `/dev/null` on Unix/Mac or `NUL` on Windows. Beware, as the message will still be composed before writing to the actual file (no hotwiring).

By default, exceptions occuring during logging are not caught. This is expected to change in the future, once it's decided how exceptions during logging should be handled.
"""
struct FileLogger <: _iologger
    logPaths::Dict{LogLevel, AbstractString}
    logIOs::Dict{LogLevel, T} where T <: IO
    messageLimits::Dict{Any, Int}
    flush::Bool
    append::Bool

    FileLogger(logPaths::Dict{LogLevel, String} = Dict(Info => "default.log"); flush = true, append = true) = new(logPaths, Dict{LogLevel,IO}(), Dict{Any, Int}(), flush, append)
end

CoreLogging.min_enabled_level(logger::FileLogger) = minimum(collect(keys(logger.logPaths)))

function getIO(logger::FileLogger, level::LogLevel)
    posFiles = filter(l -> l[1] <= level, collect(logger.logPaths))
    if !isempty(posFiles)
        chosenLevel = sort(posFiles, by = x -> x[1], rev = true)[1][1]
        # Make sure the IO is open
        if !haskey(logger.logIOs, chosenLevel)
            log = open(logger.logPaths[chosenLevel], logger.append ? "a" : "w")
            finalizer(_ -> close(log), log) # close flushes
            logger.logIOs[chosenLevel] = log
        end

        logger.logIOs[chosenLevel]
    else
        devnull
    end
end

CoreLogging.handle_message(logger::FileLogger,
                        level,
                        message,
                        _module,
                        group,
                        id,
                        file,
                        line;
                        maxlog = nothing,
                        kwargs...) = begin
    # Should we log this?
    if !checkLimits(logger, id, maxlog)
        return
    end

    io = getIO(logger, level)
    log!(io, level, string(message), _module, group, file, line; kwargs...)
    logger.flush ? flush(io) : nothing
    nothing
end


text:
using LikelihoodProfiler
### Derivative free optimization tests
# The following NLopt derivative-free algorithms are compared
dfo_algorithms = [
    :LN_NELDERMEAD, # Nelder Mead
    # worse
    :LN_BOBYQA, # BOBYQA algorithm for bound constrained optimization without derivatives
    :LN_PRAXIS, # "PRAXIS" gradient-free local optimization via the "principal-axis method"
    # errors
    :LN_SBPLX, # Subplex (a variant of Nelder-Mead that uses Nelder-Mead on a sequence of subspaces)
    :LN_COBYLA, # Constrained Optimization BY Linear Approximations
    :LN_NEWUOA,
]

@testset "testing dfo algorithms" begin
    [test_alg(alg; bounds=(-Inf,Inf)) for alg in dfo_algorithms]
end


text:
import Base: send

"""
    IRC(;
        server::AbstractString=error("No server given"),
        channel::AbstractString=error("No channel given"),
        port::Int=6667,
        nick::AbstractString=randstring(16),
    )

Initialize a new IRC channel source.

# Arguments
* `server::AbstractString=error("No server given")`: Server to connect to.
* `channel::AbstractString=error("No channel given")`: Channel to join.
* `port::Int=6667`: Port to connect via.
* `nick::AbstractString=randstring(16)`: Nickname to assume.
"""
struct IRC <: Source
    conn::TCPSocket  # Connection to the channel.

    function IRC(;
        server::AbstractString=error("No server given"),
        channel::AbstractString=error("No channel given"),
        port::Int=6667,
        nick::AbstractString=randstring(16),
    )
        s = randstring(16)  # TODO: Make a "real" user.
        conn = connect(server, port)
        write(conn, "PASS none\nNICK $nick\nUSER $s $s $s $s\nJOIN $channel\n")

        new(conn)
    end
end

function listen(source::IRC, channel::Channel{Message})
    while true
        s = readline(source.conn)
        if startswith(s, "PING")
            write(source.conn, "PONG $(String(split(s)[end]))\n")
        elseif contains(s, ":Nickname is already in use.")
            info("Nickname is already in use; changing nickname.")
            write(source.conn, "NICK $(randstring(16))\n")
        elseif !all(isspace, s)
            tokens = map(x -> String(x), split(s, " "; limit=2))
            put!(channel, IRCMessage(tokens[2], tokens[1]))
        end
    end
end

function deliver(source::IRC, msg::AbstractString)
    # Messages need to follow this specification:
    # https://en.wikipedia.org/wiki/List_of_Internet_Relay_Chat_commands
    write(source.conn, endswith(msg, "\n") ? msg : "$msg\n")
end

"""
    IRCMessage(body::AbstractString, author::AbstractString) -> IRCMessage

Create a new IRC message.

# Arguments
* `body::AbstractString`: Message contents.
* `author::AbstractString`: Author of the message.
"""
struct IRCMessage <: Message
    body::AbstractString
    author::AbstractString

    function IRCMessage(body::AbstractString, author::AbstractString)
        new(body, author)
    end
end


text:
#####
##### getindex
#####

function rrule(::typeof(getindex), x::Array{<:Number}, inds...)
    # removes any logical indexing, CartesianIndex etc
    # leaving us just with a tuple of Int, Arrays of Int and Ranges of Int
    plain_inds = Base.to_indices(x, inds)
    y = getindex(x, plain_inds...)
    function getindex_pullback(ȳ)
        function getindex_add!(Δ)
            # this a optimizes away for simple cases
            for (ȳ_ii, ii) in zip(ȳ, Iterators.product(plain_inds...))
                Δ[ii...] += ȳ_ii
            end
            return Δ
        end

        x̄ = InplaceableThunk(getindex_add!, @thunk(getindex_add!(zero(x))))
        īnds = broadcast(Returns(NoTangent()), inds)
        return (NoTangent(), x̄, īnds...)
    end

    return y, getindex_pullback
end


text:
using Flux, Gym, Printf
using Flux.Tracker: data
using Flux.Optimise: _update_params!
using Statistics: mean
using DataStructures: CircularBuffer
using CuArrays

#Load game environment

env = PendulumEnv()

# ----------------------------- Parameters -------------------------------------

STATE_SIZE = length(reset!(env)) # returns state from obs space
ACTION_SIZE = 1#length(env.actions)
ACTION_BOUND = 2#env.action_space.hi
MAX_REWARD = 0f0 # Max reward in a timestep
MAX_EP = 15_000
MAX_EP_LENGTH = 1000
SEQ_LEN = 4

# ------------------------------ Model Architecture ----------------------------

model = Chain(Dense(STATE_SIZE, 24, relu),
              Dense(24, 48, relu),
              Dense(48, ACTION_SIZE)) |> gpu

η = 3f-2

opt = ADAM(η)

loss(r) = Flux.mse(r, MAX_REWARD)

# ----------------------------- Helper Functions -------------------------------

function update(rewards)
  Flux.back!(loss(rewards))
  _update_params!(opt, params(model))
  # grads = Tracker.gradient(()->loss(rewards), params(model))
  # for p in params(model)
  #   update!(opt, p, grads[p])
  # end
end

function episode!(env, train=true)
  total_reward = 0f0
  rewards = []
  s = reset!(env)
  for ep=1:MAX_EP_LENGTH
    a = model(s)
    s′, r, done, _ = step!(env, a)
    total_reward += data(r)[1]
    s = s′
    if train
      push!(rewards, r)
      if ep == MAX_EP_LENGTH || ep % SEQ_LEN == 0
        rewards = vcat(rewards...)
        update(rewards)
	rewards = []
        env.state = param(data(env.state))
        s = Gym._get_obs(env)
      end
    end
  end

  total_reward
end

# -------------------------------- Testing -------------------------------------

function test()
  score_mean = 0f0
  for e=1:100
    total_reward = episode!(env, false)
    score_mean += total_reward / 100
  end
  return score_mean
end

# ------------------------------ Training --------------------------------------

for e=1:MAX_EP
  total_reward = episode!(env)
  total_reward = @sprintf "%9.3f" total_reward
  print("Episode: $e | Score: $total_reward | ")
  score_mean = test()
  score_mean = @sprintf "%9.3f" score_mean
  println("Mean score over 100 test episodes: $score_mean")
end


text:
#############
# Methods
#############

function SddMgr(::Type{T}, vtree::Vtree)::T where {T<:SddMgr}
    node2dag(SddMgr(TrimMgrNode, vtree[end]))
end

function SddMgr(::Type{T}, vtree::VtreeNode)::T where {T<:SddMgrNode}
    SddMgr(T, NodeType(vtree), vtree)
end

function SddMgr(::Type{T}, ::Inner, vtree::VtreeNode)::T where {T<:SddMgrNode}
    T(SddMgr(T, vtree.left), SddMgr(T, vtree.right))
end

function SddMgr(::Type{T}, ::Leaf, vtree::VtreeNode)::T where {T<:SddMgrNode}
    @assert num_variables(vtree) == 1
    T(first(variables(vtree)))
end

sdd_size(sdd::Sdd) = mapreduce(n -> num_children(n), +, ⋁_nodes(sdd); init=0) # defined as the number of `elements`; length(⋀_nodes(sdd)) also works but undercounts in case the compiler decides to cache elements

sdd_num_nodes(sdd::Sdd) = length(⋁_nodes(sdd)) # defined as the number of `decisions`

function compile_clause(mgr::SddMgr, clause::Δ)::SddNode
    compile_clause(mgr, cnf[end])
 end

function compile_clause(mgr::Union{SddMgr,SddMgrNode}, clause::ΔNode)::SddNode
    @assert GateType(clause) isa ⋁Gate
    literals = children(clause)
    clauseΔ = compile(mgr, literal(literals[1]))
    for l in literals[2:end]
       clauseΔ = clauseΔ | compile(mgr, literal(l))
    end
    clauseΔ
 end

 function compile_cnf(mgr::SddMgr, cnf::Δ, strategy="tree", progress=false)::SddNode
    compile_cnf(mgr, cnf[end], strategy, progress)
 end

 function compile_cnf(mgr::SddMgr, cnf::ΔNode, strategy="tree", progress=false)::SddNode
    if strategy == "naive"
        compile_cnf_naive(mgr, cnf, progress)
    elseif strategy == "tree"
        compile_cnf_tree(mgr, cnf, progress)
    else
        error("Invalid compilation strategy")
    end
 end

 function compile_cnf_naive(mgr::SddMgr, cnf::ΔNode, progress=false)::SddNode
    @assert GateType(cnf) isa ⋀Gate
    cnfΔ = compile(true)
    i = 0
    for clause in children(cnf)
       i = i+1
       cnfΔ = cnfΔ & compile_clause(mgr, clause)
       progress && println((100*i/num_children(cnf[end])),"%: Number of edges: ", num_edges(node2dag(cnfΔ)))
    end
    cnfΔ
 end

 function compile_cnf_tree(mgr::SddMgr, cnf::ΔNode, progress=false)::SddNode
    @assert GateType(cnf) isa ⋀Gate
    compile_cnf_tree(NodeType(mgr[end]), mgr[end], children(cnf), variable_scopes(cnf), progress)
 end

 function compile_cnf_tree(::Inner, mgr::SddMgrNode, clauses::Vector{<:ΔNode},
                           scopes::Dict{ΔNode,BitSet}, progress=false)::SddNode
    left_clauses = filter(c -> scopes[c] ⊆ variables(mgr.left), clauses)
    leftΔ = compile_cnf_tree(NodeType(mgr.left), mgr.left, left_clauses, scopes, progress)
    right_clauses = filter(c -> scopes[c] ⊆ variables(mgr.right), clauses)
    rightΔ = compile_cnf_tree(NodeType(mgr.right), mgr.right, right_clauses, scopes, progress)
    progress && print("Compiled left ($(sdd_size(node2dag(leftΔ)))) and right ($(sdd_size(node2dag(rightΔ))))")
    joinΔ = leftΔ & rightΔ
    mixed_clauses = setdiff(clauses, left_clauses, right_clauses)
    progress && print(" with $(length(mixed_clauses)) clauses")
    # left_degree(c) = begin
    #     # length(scopes[c] ∩ variables(mgr.left)) #- length(scopes[c] ∩ variables(mgr.right))
    #     -num_children(c)
    # end
    # sort!(mixed_clauses, by = left_degree)
    for clause in mixed_clauses
        joinΔ = joinΔ & compile_clause(mgr, clause)
    end
    progress && println(" into sdd of size $(sdd_size(node2dag(joinΔ)))")
    joinΔ
 end

 function compile_cnf_tree(::Leaf, mgr::SddMgrNode, clauses::Vector{<:ΔNode},
                            scopes::Dict{ΔNode,BitSet}, progress=false)::SddNode
    joinΔ = compile(true)
    for clause in clauses
        joinΔ = joinΔ & compile_clause(mgr, clause)
    end
    joinΔ #TODO make foldr
 end


text:
using DataStructures

const MonSigPair{I, M} = Tuple{M, Tuple{I, M}}
const Pair{I, M} = Tuple{MonSigPair{I, M}, MonSigPair{I, M}}
const Basis{I, M} = Dict{I, Vector{Tuple{M, M}}}
const Syz{I, M} = Dict{I, Vector{M}}

function gb_size(ctx::SigPolynomialΓ{I, M}, G::Basis{I, M}) where {I, M}

    size = 0
    for (i, Gi) in G
        for (g, _) in Gi
            size += length(ctx((i, g))[:poly])
        end
    end
    return size
end

function degree(ctx::SigPolynomialΓ{I, M}, p::MonSigPair{I, M}) where {I, M}
    degree(ctx.po.mo, p[1]) + degree(ctx.po.mo, p[2][2])
end

function new_syz(ctx::SigPolynomialΓ, length)
    I = pos_type(ctx)
    M = eltype(ctx.po.mo)
    Dict([(I(i), M[]) for i in 1:length])
end

function new_basis(ctx::SigPolynomialΓ, length)
    M = eltype(ctx.po.mo)
    Dict([(pos_type(ctx)(i), Tuple{M, M}[]) for i in 1:length])
end

function new_basis(ctx::SigPolynomialΓ, G::Basis{I, M}) where {I, M}
    Dict([(posit_key, Tuple{M, M}[]) for posit_key in keys(G)])
end

function new_basis_elem!(ctx::SigPolynomialΓ{I, M},
                         G::Basis{I, M},
                         g::Tuple{I, M},
                         lm = leadingmonomial(ctx, g)) where {I, M}

    push!(G[g[1]], (g[2], lm))
end

pos(ctx::SigPolynomialΓ{I, M}, p::MonSigPair{I, M}) where {I, M} = pos(ctx, p[2])

gettag(ctx::SigPolynomialΓ{I, M}, p::MonSigPair{I, M}) where {I, M} = gettag(ctx, p[2])

getattkey(ctx::SigPolynomialΓ{I, M}, p::MonSigPair{I, M}) where {I, M} = getattkey(ctx, p[2])

function pretty_print(ctx::SigPolynomialΓ{I, M}, a::MonSigPair{I, M}) where {I, M}
    "$(Vector{Int}(ctx.po.mo[a[1][1]].exponents)), $(Int(ctx.ord_indices[a[2][1]][:position])), $(Vector{Int}(ctx.po.mo[a[2][2]].exponents))"
end

function pretty_print(ctx::SigPolynomialΓ{I, M}, a::Tuple{I, M}) where {I, M}
    "$(Vector{Int}(ctx.po.mo[a[2]].exponents)), $(Int(ctx.ord_indices[a[1]][:position]))"
end

function nullmonsigpair(ctx::SigPolynomialΓ)
    (zero(mon_type(ctx)), (zero(pos_type(ctx)), zero(mon_type(ctx))))
end

isnull(p::MonSigPair) = iszero(p[2][1])

struct MPairOrdering{SΓ <: SigPolynomialΓ}<:Base.Order.Ordering
    ctx::SΓ
end
mpairordering(ctx::SΓ) where SΓ = MPairOrdering{SΓ}(ctx)

function Base.Order.lt(porder::MPairOrdering{SΓ},
                       a::MonSigPair{I, M},
                       b::MonSigPair{I, M}) where {I, M, SΓ <: SigPolynomialΓ{I, M}}
    amul, bmul = mul(porder.ctx, a...), mul(porder.ctx, b...)
    if amul == bmul
        return a[2][2] < b[2][2]
    end
    lt(porder.ctx, amul, bmul)
end

struct PairOrdering{SΓ <: SigPolynomialΓ}<:Base.Order.Ordering
    ord::MPairOrdering{SΓ}
end
pairordering(ctx::SΓ) where SΓ = PairOrdering{SΓ}(mpairordering(ctx))

function Base.Order.lt(porder::PairOrdering{SΓ},
                       a::Pair{I, M},
                       b::Pair{I, M}) where {I, M, SΓ <: SigPolynomialΓ{I, M}}
    if mul(porder.ord.ctx, first(a)...) == mul(porder.ord.ctx, first(b)...)
        if !(isnull(a[2])) && !(isnull(b[2]))
            return Base.Order.lt(porder.ord, a[2], b[2])
        end
    end
    Base.Order.lt(porder.ord, first(a), first(b))
end

const PairSet{I, M, SΓ} = SortedSet{Pair{I, M}, PairOrdering{SΓ}}
const MonSigSet{I, M, SΓ} = Set{MonSigPair{I, M}}

function mpairset(ctx::SigPolynomialΓ{I, M},
                  pairs::Vector{MonSigPair{I, M}}) where {I, M}
    Set(pairs)
end

function mpairset(ctx::SigPolynomialΓ{I, M}) where {I, M}
    mpairset(ctx, MonSigPair{I, M}[])
end

function pairset(ctx::SigPolynomialΓ{I, M},
                 pairs::Vector{Pair{I, M}}) where {I, M}
    SortedSet(pairs, pairordering(ctx))
end

function pairset(ctx::SigPolynomialΓ{I, M}) where {I, M}
    pairset(ctx, Pair{I, M}[])
end

function pairs!(ctx::SΓ,
                pairset::PairSet{I, M, SΓ},
                sig::Tuple{I, M},
                lm_sig::M,
                G::Basis{I, M},
                H::Syz{I, M};
                enable_lower_pos_rewrite = true) where {I, M, SΓ <: SigPolynomialΓ{I, M}}

    posit_key = sig[1]
    for (i, Gi) in G
        for (j, (g, lm)) in enumerate(Gi)
            g_sig = (i, g)
            (posit_key, ctx(sig)[:sigratio]) == (i, ctx(g_sig)[:sigratio]) && continue
            m = lcm(ctx.po.mo, lm, lm_sig)
            a = div(ctx.po.mo, m, lm_sig)
            rewriteable_syz(ctx, a, sig, G, H) && continue
            b = div(ctx.po.mo, m, lm)
            if enable_lower_pos_rewrite || i == posit_key
                rewriteable(ctx, b, g_sig, j, G, H) && continue
            end
            if lt(ctx, (posit_key, ctx(sig)[:sigratio]), (i, ctx(g_sig)[:sigratio]))
                push!(pairset, ((b, g_sig), (a, sig)))
            else
                push!(pairset, ((a, sig), (b, g_sig)))
            end
        end
    end
end

function pair!(ctx::SΓ,
               pairset::PairSet{I, M, SΓ},
               sig::Tuple{I, M}) where {I, M, SΓ <: SigPolynomialΓ{I, M}}

    !(iszero(ctx(sig)[:poly])) && push!(pairset, ((one(ctx.po.mo), sig), nullmonsigpair(ctx)))
end

#.. Rewrite functions for add rewrite order

function new_rewriter!(ctx::SΓ,
                       pairset::PairSet{I, M, SΓ},
                       sig::Tuple{I, M}) where {I, M, SΓ <: SigPolynomialΓ{I, M}}
    pos, m = sig
    crit = p -> (divides(ctx, sig, mul(ctx, p[1]...)) || (!(isnull(p[2])) && divides(ctx, sig, mul(ctx, p[2]...))))
    for p in pairset
        if crit(p)
            delete!(pairset, p)
        end
    end
end

function rewriteable(ctx::SigPolynomialΓ{I, M},
                     m::M,
                     sig::Tuple{I, M},
                     indx,
                     G::Basis{I, M}) where {I, M}

    msig = mul(ctx.po.mo, m, sig[2])
    pos = sig[1]
    for (g, lm) in view(G[pos], indx + 1:length(G[pos]))
        divides(ctx.po.mo, g, msig) && return true
    end

    return false
end

function rewriteable_syz(ctx::SigPolynomialΓ{I, M},
                         m::M,
                         sig::Tuple{I, M},
                         G::Basis{I, M},
                         H::Syz{I, M}) where {I, M}

    msig = mul(ctx, m, sig)
    pos = sig[1]
    for h in H[pos]
        if divides(ctx.po.mo, h, msig[2])
            return true
        end
    end
    pos_t = pos_type(ctx)
    for i in filter(j -> ctx.ord_indices[j][:position] < ctx.ord_indices[pos][:position], keys(G))
        for (g, lm) in G[i]
            divides(ctx.po.mo, lm, msig[2]) && return true
        end
    end
    return false
end

function rewriteable(ctx::SigPolynomialΓ{I, M},
                     m::M,
                     sig::Tuple{I, M},
                     indx,
                     G::Basis{I, M},
                     H::Syz{I, M}) where {I, M}

    rewriteable_syz(ctx, m, sig, G, H) || rewriteable(ctx, m, sig, indx, G)
end

# selection

function select!(ctx::SΓ,
                 pairs::PairSet{I, M, SΓ},
                 cond::Val{S};
                 select_both = true) where {I, M, SΓ <: SigPolynomialΓ{I, M}, S}

    nselected = 1
    pair = pop!(pairs)
    indx = pos(ctx, pair[1])
    sig_degree = degree(ctx, pair[1])
    are_pairs = false
    selected = mpairset(ctx, [pair[1]])
    if select_both && !(isnull(pair[2]))
        push!(selected, pair[2])
        are_pairs = true
    end

    if S == :one
        cond = p -> false
    elseif S == :deg_and_pos
        cond = p -> pos(ctx, p[1]) == indx && degree(ctx, p[1]) == sig_degree
    elseif S == :pos
        cond = p -> pos(ctx, p[1]) == indx
    else
        error("Select method must be one of :one, :deg_and_pos or :pos")
    end

    while !(isempty(pairs))
        if !(cond(first(pairs)))
            break
        end
        p = pop!(pairs)
        push!(selected, first(p))
        select_both && push!(selected, p[2])
        nselected += 1
    end
    selected, are_pairs, nselected, sig_degree
end


text:
include("parallelGeneration.jl")

import Statistics.mean

setRNGs(1)
nt = Threads.nthreads()
out = Vector{Float64}(undef, nt)

N0 = 2^25
foo!(out, N0)
@test mean(out) ≈ 0.5 atol=0.001