def combine_tensors(combination: str, tensors: List[torch.Tensor]) -> torch.Tensor:
    """
    Combines a list of tensors using element-wise operations and concatenation, specified by a
    `combination` string.  The string refers to (1-indexed) positions in the input tensor list,
    and looks like `"1,2,1+2,3-1"`.

    We allow the following kinds of combinations : `x`, `x*y`, `x+y`, `x-y`, and `x/y`,
    where `x` and `y` are positive integers less than or equal to `len(tensors)`.  Each of
    the binary operations is performed elementwise.  You can give as many combinations as you want
    in the `combination` string.  For example, for the input string `"1,2,1*2"`, the result
    would be `[1;2;1*2]`, as you would expect, where `[;]` is concatenation along the last
    dimension.

    If you have a fixed, known way to combine tensors that you use in a model, you should probably
    just use something like `torch.cat([x_tensor, y_tensor, x_tensor * y_tensor])`.  This
    function adds some complexity that is only necessary if you want the specific combination used
    to be `configurable`.

    If you want to do any element-wise operations, the tensors involved in each element-wise
    operation must have the same shape.

    This function also accepts `x` and `y` in place of `1` and `2` in the combination
    string.
    """
    if len(tensors) > 9:
        raise ConfigurationError("Double-digit tensor lists not currently supported")
    combination = combination.replace("x", "1").replace("y", "2")
    to_concatenate = [_get_combination(piece, tensors) for piece in combination.split(",")]
    return torch.cat(to_concatenate, dim=-1)
Combines a list of tensors using element-wise operations and concatenation, specified by a
`combination` string.  The string refers to (1-indexed) positions in the input tensor list,
and looks like `"1,2,1+2,3-1"`.

We allow the following kinds of combinations : `x`, `x*y`, `x+y`, `x-y`, and `x/y`,
where `x` and `y` are positive integers less than or equal to `len(tensors)`.  Each of
the binary operations is performed elementwise.  You can give as many combinations as you want
in the `combination` string.  For example, for the input string `"1,2,1*2"`, the result
would be `[1;2;1*2]`, as you would expect, where `[;]` is concatenation along the last
dimension.

If you have a fixed, known way to combine tensors that you use in a model, you should probably
just use something like `torch.cat([x_tensor, y_tensor, x_tensor * y_tensor])`.  This
function adds some complexity that is only necessary if you want the specific combination used
to be `configurable`.

If you want to do any element-wise operations, the tensors involved in each element-wise
operation must have the same shape.

This function also accepts `x` and `y` in place of `1` and `2` in the combination
string.
allennlp/nn/util.py