import torch


def replace_binary_continuous_product(x_lo, x_up, dtype=torch.float64):
    """
    We replace the product between a binary variable α and a continuous
    variable x by a slack variable s, such that s = α * x. To impose this
    constraint on s, assuming that x is bounded between [xₗₒ, xᵤₚ], we
    introduce the following linear constraints
    s ≥ α*xₗₒ
    s ≤ α*xᵤₚ
    x - s + (α - 1)*xᵤₚ ≤ 0
    x - s + (α - 1)*xₗₒ ≥ 0
    We write these constraints concisely as
    Aₓ*x + Aₛ*s + A_alpha*α ≤ rhs
    @param x_lo The lower bound of x.
    @param x_up The upper bound of x.
    @param (A_x, A_s, A_alpha, rhs) A_x, A_s, A_alpha, rhs are all arrays of
    length 4.
    """
    if isinstance(x_lo, float):
        x_lo = torch.tensor(x_lo, dtype=dtype)
    if isinstance(x_up, float):
        x_up = torch.tensor(x_up, dtype=dtype)
    assert (isinstance(x_lo, torch.Tensor))
    assert (x_lo <= x_up)
    A_x = torch.tensor([0, 0, 1, -1], dtype=dtype)
    A_s = torch.tensor([-1, 1, -1, 1], dtype=dtype)
    A_alpha = torch.stack((x_lo, -x_up, x_up, -x_lo))
    rhs = torch.zeros(4, dtype=dtype)
    rhs = torch.stack(
        (torch.tensor(0, dtype=dtype), torch.tensor(0,
                                                    dtype=dtype), x_up, -x_lo))
    return (A_x, A_s, A_alpha, rhs)