import torch


def create_optimizer(model: torch.nn.Module, optimizer_name: str, learning_rate: float, weight_decay: float = 0.0,
                     momentum: float = 0.0) -> torch.optim.Optimizer:
    """Creates the optimizer for the model.

    Args:
        model: The Module object representing the network.
        optimizer_name: The name of the optimizer to use. Only Adadelta, Adam, SGD, and RMSprop are supported.
        learning_rate: The initial learning rate.
        weight_decay: Weight decay value (L2 penalty)
        momentum: Momentum factor.

    Returns:
        The optimizer object.

    Raises:
        ValueError: If the optimizer is unknown.
    """
    if optimizer_name.lower() == "adadelta":
        optimizer = torch.optim.Adadelta(model.parameters(), learning_rate, weight_decay=weight_decay)
    elif optimizer_name.lower() == "adam":
        optimizer = torch.optim.Adam(model.parameters(), learning_rate, weight_decay=weight_decay)
    elif optimizer_name.lower() == "sgd":
        optimizer = torch.optim.SGD(model.parameters(), learning_rate, momentum,
                                    weight_decay=weight_decay)
    elif optimizer_name.lower() == "rmsprop":
        optimizer = torch.optim.RMSprop(model.parameters(), learning_rate, weight_decay=weight_decay,
                                        momentum=momentum)
    else:
        raise ValueError("SystemLog: The optimizer must be Adadelta, Adam, SGD, or RMSprop "
                         "(optimizer: {})".format(optimizer_name))

    return optimizer