jiahuimbzuai/CoQuIR huggingface dataset:
//  [python]
def orthogonal_random_matrix_(w):
    """Initialize the matrix w in-place to compute orthogonal random features.

    The matrix is initialized such that its columns are orthogonal to each
    other (in groups of size `rows`) and their norms is drawn from the
    chi-square distribution with `rows` degrees of freedom (namely the norm of
    a `rows`-dimensional vector distributed as N(0, I)).

    Arguments
    ---------
        w: float tensor of size (rows, columns)
    """
    rows, columns = w.shape
    start = 0
    while start < columns:
        end = min(start + rows, columns)
        block = torch.randn(rows, rows, device=w.device)
        norms = torch.sqrt(torch.einsum('ab,ab->a', block, block))
        Q, _ = torch.qr(block)
        w[:, start:end] = Q[:, :end - start] * norms[None, :end - start]
        start += rows
//  [python]
def orthogonal_random_matrix_(w):
    """Initialize the matrix w in-place to compute orthogonal random features.

    The matrix is initialized such that its columns are orthogonal to each
    other (in groups of size `rows`) and their norms is drawn from the
    chi-square distribution with `rows` degrees of freedom (namely the norm of
    a `rows`-dimensional vector distributed as N(0, I)).

    Arguments
    ---------
        w: float tensor of size (rows, columns)
    """
    rows, columns = w.shape
    start = 0
    while start < columns:
        end = min(start + rows, columns)
        block = torch.randn(rows, rows, device=w.device)
        norms = torch.sqrt(torch.einsum('ab,ab->a', block, block))
        Q, _ = torch.linalg.qr(block)
        w[:, start:end] = Q[:, :end - start] * norms[None, :end - start]
        start += rows
//  [python]
def test_qr(A):
    q, r = geoopt.linalg.qr(A)
    with torch.no_grad():
        for i, a in enumerate(A):
            qt, rt = torch.qr(a)
            np.testing.assert_allclose(q.detach()[i], qt.detach())
            np.testing.assert_allclose(r.detach()[i], rt.detach())
//  [python]
def test_qr(A):
    q, r = geoopt.linalg.qr(A)
    with torch.no_grad():
        for i, a in enumerate(A):
            qt, rt = torch.linalg.qr(a)
            np.testing.assert_allclose(q.detach()[i], qt.detach())
            np.testing.assert_allclose(r.detach()[i], rt.detach())
//  [python]
def qr(input):
    q, r = torch.qr(input)
    q.backward(torch.ones_like(q))
    return q
//  [python]
def qr(input):
    q, r = torch.linalg.qr(input)
    q.backward(torch.ones_like(q))
    return q
//  [python]
def get_latent(self, weights, person_2 = False):
        b = weights.shape[0]

        bases = self.bases + 1e-8

        Q, R = torch.qr(bases.T)  # get eignvector, orthogonal [n1, n2, n3, n4]

        if weights is None:
            return Q
        else:
            input_diag = torch.diag_embed(weights)  # alpha, diagonal matrix
            out = torch.matmul(input_diag, Q.T)
            out = torch.sum(out, dim=1)
            return out.view(b, -1, self.dim) + self.delta.view(-1, self.dim)
//  [python]
def get_latent(self, weights, person_2 = False):
        b = weights.shape[0]

        bases = self.bases + 1e-8

        Q, R = torch.linalg.qr(bases.T)  # get eignvector, orthogonal [n1, n2, n3, n4]

        if weights is None:
            return Q
        else:
            input_diag = torch.diag_embed(weights)  # alpha, diagonal matrix
            out = torch.matmul(input_diag, Q.T)
            out = torch.sum(out, dim=1)
            return out.view(b, -1, self.dim) + self.delta.view(-1, self.dim)
//  [python]
def get_latent(self, weights, person_2 = False):
        b = weights.shape[0]

        bases = self.bases + 1e-8
        Q, R = torch.qr(bases.T)  # get eignvector, orthogonal [n1, n2, n3, n4]

        if weights is None:
            return Q
        else:
            input_diag = torch.diag_embed(weights)  # alpha, diagonal matrix
            out = torch.matmul(input_diag, Q.T)
            out = torch.sum(out, dim=1)

            return out.view(b, -1, self.dim) + self.delta.view(-1, self.dim)
//  [python]
def get_latent(self, weights, person_2 = False):
        b = weights.shape[0]

        bases = self.bases + 1e-8
        Q, R = torch.linalg.qr(bases.T)  # get eignvector, orthogonal [n1, n2, n3, n4]

        if weights is None:
            return Q
        else:
            input_diag = torch.diag_embed(weights)  # alpha, diagonal matrix
            out = torch.matmul(input_diag, Q.T)
            out = torch.sum(out, dim=1)

            return out.view(b, -1, self.dim) + self.delta.view(-1, self.dim)
//  [python]
def orthogonal_matrix_chunk(cols, qr_uniform_q=False, device=None, qr_on_cpu=True):
    unstructured_block = torch.randn((cols, cols), device=device)
    if qr_on_cpu:
        # apparently torch.qr is known to be faster on cpu in many cases?
        # https://discuss.pytorch.org/t/doing-qr-decomposition-on-gpu-is-much-slower-than-on-cpu/21213
        q, r = torch.qr(unstructured_block.cpu(), some=True)
        # but gives memory leak in some cases...
    else:
        q, r = torch.qr(unstructured_block, some=True)
    q, r = map(lambda t: t.to(device), (q, r))

    if qr_uniform_q:
        d = torch.diag(r, 0)
        q *= d.sign()
    return q.t()
//  [python]
def orthogonal_matrix_chunk(cols, qr_uniform_q=False, device=None, qr_on_cpu=True):
    unstructured_block = torch.randn((cols, cols), device=device)
    if qr_on_cpu:
        # apparently torch.qr is known to be faster on cpu in many cases?
        # https://discuss.pytorch.org/t/doing-qr-decomposition-on-gpu-is-much-slower-than-on-cpu/21213
        q, r = torch.linalg.qr(unstructured_block.cpu(), mode='reduced')
        # but gives memory leak in some cases...
    else:
        q, r = torch.linalg.qr(unstructured_block, mode='reduced')
    q, r = map(lambda t: t.to(device), (q, r))

    if qr_uniform_q:
        d = torch.diag(r, 0)
        q *= d.sign()
    return q.t()
//  [python]
def get_latent(self, weights, person_2 = False):
        b = weights.shape[0]

        if not person_2:
            bases = self.bases + 1e-8
        else:
            if not self.args.same_bases:
                bases = self.bases_2 + 1e-8
            else:
                bases = self.bases + 1e-8
        Q, R = torch.qr(bases.T)  # get eignvector, orthogonal [n1, n2, n3, n4]

        if weights is None:
            return Q
        else:
            input_diag = torch.diag_embed(weights)  # alpha, diagonal matrix
            out = torch.matmul(input_diag, Q.T)
            out = torch.sum(out, dim=1)
            if not person_2:
                return out.view(b, -1, self.dim) + self.delta.view(-1, self.dim)
            else:
                return out.view(b, -1, self.dim) + self.delta_2.view(-1, self.dim)
//  [python]
def get_latent(self, weights, person_2 = False):
        b = weights.shape[0]

        if not person_2:
            bases = self.bases + 1e-8
        else:
            if not self.args.same_bases:
                bases = self.bases_2 + 1e-8
            else:
                bases = self.bases + 1e-8
        Q, R = torch.linalg.qr(bases.T)  # get eignvector, orthogonal [n1, n2, n3, n4]

        if weights is None:
            return Q
        else:
            input_diag = torch.diag_embed(weights)  # alpha, diagonal matrix
            out = torch.matmul(input_diag, Q.T)
            out = torch.sum(out, dim=1)
            if not person_2:
                return out.view(b, -1, self.dim) + self.delta.view(-1, self.dim)
            else:
                return out.view(b, -1, self.dim) + self.delta_2.view(-1, self.dim)
//  [python]
a = torch.tensor([[12., -51, 4], [6, 167, -68], [-4, 24, -41]])
old_q, old_r = torch.qr(a)
//  [python]
a = torch.tensor([[12., -51, 4], [6, 167, -68], [-4, 24, -41]])
old_q, old_r = torch.linalg.qr(a)
//  [python]
def qr(A: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:  # pragma: no cover
    """
    Like torch.linalg.qr.
    """
    if hasattr(torch, "linalg") and hasattr(torch.linalg, "qr"):
        # PyTorch version >= 1.9
        return torch.linalg.qr(A)
    return torch.qr(A)
//  [python]
def qr(A: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:  # pragma: no cover
    """
    Like torch.linalg.qr.
    """
    return torch.linalg.qr(A)
//  [python]
def orthogonalize_weights(tensor, act):
    r"""Fills the input `Tensor` with a (semi) orthogonal matrix, as
    described in `Exact solutions to the nonlinear dynamics of learning in deep
    linear neural networks` - Saxe, A. et al. (2013). The input tensor must have
    at least 2 dimensions, and for tensors with more than 2 dimensions the
    trailing dimensions are flattened.

    Args:
        tensor: an n-dimensional `torch.Tensor`, where :math:`n \geq 2`
        gain: optional scaling factor

    Examples:
        >>> w = torch.empty(3, 5)
        >>> nn.init.orthogonal_(w)
    """
    tensor = tensor.clone().detach()  # @mst: avoid modifying the original tensor
    gain = init.calculate_gain(act)

    if tensor.ndimension() < 2:
        raise ValueError("Only tensors with 2 or more dimensions are supported")

    rows = tensor.size(0)
    cols = tensor.numel() // rows
    # flattened = tensor.new(rows, cols).normal_(0, 1)
    flattened = tensor.view(rows, cols)  # @mst: do NOT reinit the tensor

    if rows < cols:
        flattened.t_()

    # Compute the qr factorization
    q, r = torch.qr(flattened)  # q: (rows, cols), r: (cols, cols) if rows > cols.

    # Make Q uniform according to https://arxiv.org/pdf/math-ph/0609050.pdf
    d = torch.diag(r, 0)  # d: (cols)
    ph = d.sign()
    q *= ph  # (rows, cols) * (cols) => (rows, cols)

    if rows < cols:
        q.t_()

    with torch.no_grad():
        tensor.view_as(q).copy_(q)
        tensor.mul_(gain)
    return tensor
//  [python]
def orthogonalize_weights(tensor, act):
    r"""Fills the input `Tensor` with a (semi) orthogonal matrix, as
    described in `Exact solutions to the nonlinear dynamics of learning in deep
    linear neural networks` - Saxe, A. et al. (2013). The input tensor must have
    at least 2 dimensions, and for tensors with more than 2 dimensions the
    trailing dimensions are flattened.

    Args:
        tensor: an n-dimensional `torch.Tensor`, where :math:`n \geq 2`
        gain: optional scaling factor

    Examples:
        >>> w = torch.empty(3, 5)
        >>> nn.init.orthogonal_(w)
    """
    tensor = tensor.clone().detach()  # @mst: avoid modifying the original tensor
    gain = init.calculate_gain(act)

    if tensor.ndimension() < 2:
        raise ValueError("Only tensors with 2 or more dimensions are supported")

    rows = tensor.size(0)
    cols = tensor.numel() // rows
    # flattened = tensor.new(rows, cols).normal_(0, 1)
    flattened = tensor.view(rows, cols)  # @mst: do NOT reinit the tensor

    if rows < cols:
        flattened.t_()

    # Compute the qr factorization
    q, r = torch.linalg.qr(flattened)  # q: (rows, cols), r: (cols, cols) if rows > cols.

    # Make Q uniform according to https://arxiv.org/pdf/math-ph/0609050.pdf
    d = torch.diag(r, 0)  # d: (cols)
    ph = d.sign()
    q *= ph  # (rows, cols) * (cols) => (rows, cols)

    if rows < cols:
        q.t_()

    with torch.no_grad():
        tensor.view_as(q).copy_(q)
        tensor.mul_(gain)
    return tensor
//  [python]
def QRreduction(datas):
    
    #ndatas = torch.linalg.qr(datas.permute(0,2,1), mode='reduced').R
    ndatas = torch.qr(datas.permute(0,2,1)).R
    ndatas = ndatas.permute(0,2,1)
    return ndatas
//  [python]
def QRreduction(datas):
    
    ndatas = torch.linalg.qr(datas.permute(0,2,1), mode='reduced').R
    ndatas = ndatas.permute(0,2,1)
    return ndatas
//  [python]
def __init__(self, channels, num_splits=4, no_jacobian=False, **kwargs):  # pylint: disable=unused-argument
        super().__init__()
        assert num_splits % 2 == 0
        self.channels = channels
        self.num_splits = num_splits
        self.no_jacobian = no_jacobian
        self.weight_inv = None

        if LooseVersion(torch.__version__) < LooseVersion("1.9"):
            w_init = torch.qr(torch.FloatTensor(self.num_splits, self.num_splits).normal_())[0]
        else:
            w_init = torch.linalg.qr(torch.FloatTensor(self.num_splits, self.num_splits).normal_(), "complete")[0]

        if torch.det(w_init) < 0:
            w_init[:, 0] = -1 * w_init[:, 0]
        self.weight = nn.Parameter(w_init)
//  [python]
def __init__(self, channels, num_splits=4, no_jacobian=False, **kwargs):  # pylint: disable=unused-argument
        super().__init__()
        assert num_splits % 2 == 0
        self.channels = channels
        self.num_splits = num_splits
        self.no_jacobian = no_jacobian
        self.weight_inv = None

        w_init = torch.qr(
            torch.FloatTensor(self.num_splits, self.num_splits).normal_())[0]
        if torch.det(w_init) < 0:
            w_init[:, 0] = -1 * w_init[:, 0]
        self.weight = nn.Parameter(w_init)
//  [python]
def __init__(self, channels, num_splits=4, no_jacobian=False, **kwargs):  # pylint: disable=unused-argument
        super().__init__()
        assert num_splits % 2 == 0
        self.channels = channels
        self.num_splits = num_splits
        self.no_jacobian = no_jacobian
        self.weight_inv = None

        w_init = torch.linalg.qr(
            torch.FloatTensor(self.num_splits, self.num_splits).normal_())[0]
        if torch.det(w_init) < 0:
            w_init[:, 0] = -1 * w_init[:, 0]
        self.weight = nn.Parameter(w_init)
//  [python]
def __init__(self, c, device):
        super(Invertible1x1Conv, self).__init__()
        self.conv = torch.nn.Conv1d(c, c, kernel_size=1, stride=1, padding=0, bias=False)
        self.device = device

        # Sample a random orthonormal matrix to initialize weights
        W = torch.qr(torch.FloatTensor(c, c).normal_())[0]

        # Ensure determinant is 1.0 not -1.0
        if torch.det(W) < 0:
            W[:, 0] = -1 * W[:, 0]
        W = W.view(c, c, 1)
        W = W.contiguous()
        self.conv.weight.data = W
//  [python]
def __init__(self, c, device):
        super(Invertible1x1Conv, self).__init__()
        self.conv = torch.nn.Conv1d(c, c, kernel_size=1, stride=1, padding=0, bias=False)
        self.device = device

        # Sample a random orthonormal matrix to initialize weights
        W = torch.linalg.qr(torch.FloatTensor(c, c).normal_())[0]

        # Ensure determinant is 1.0 not -1.0
        if torch.det(W) < 0:
            W[:, 0] = -1 * W[:, 0]
        W = W.view(c, c, 1)
        W = W.contiguous()
        self.conv.weight.data = W
//  [python]
def orthogonal_(tensor, gain=1):

    if tensor.ndimension() < 2:
        raise ValueError("Only tensors with 2 or more dimensions are supported")

    rows = tensor.size(0)
    cols = tensor[0].numel()
    flattened = tensor*1.0

    if rows < cols:
        flattened.t_()

    # Compute the qr factorization
    q, r = torch.qr(flattened)
    # Make Q uniform according to https://arxiv.org/pdf/math-ph/0609050.pdf
    d = torch.diag(r, 0)
    ph = d.sign()
    q *= ph

    if rows < cols:
        q.t_()

    with torch.no_grad():
        tensor.view_as(q).copy_(q)
        tensor.mul_(gain)
    return tensor
//  [python]
def orthogonal_(tensor, gain=1):

    if tensor.ndimension() < 2:
        raise ValueError("Only tensors with 2 or more dimensions are supported")

    rows = tensor.size(0)
    cols = tensor[0].numel()
    flattened = tensor*1.0

    if rows < cols:
        flattened.t_()

    # Compute the qr factorization
    q, r = torch.linalg.qr(flattened)
    # Make Q uniform according to https://arxiv.org/pdf/math-ph/0609050.pdf
    d = torch.diag(r, 0)
    ph = d.sign()
    q *= ph

    if rows < cols:
        q.t_()

    with torch.no_grad():
        tensor.view_as(q).copy_(q)
        tensor.mul_(gain)
    return tensor
//  [python]
def qr(matrix, rhs):
    # qr分解
    q, r = torch.qr(matrix)
    y = torch.matmul(q.T, rhs)
    return torch.triangular_solve(r, y).solution
//  [python]
def qr(matrix, rhs):
    # qr分解
    q, r = torch.linalg.qr(matrix)
    y = torch.matmul(q.T, rhs)
    return torch.triangular_solve(r, y).solution
//  [python]
def cca_torch(x1, x2):
    x1_flat, x2_flat = rearrange_activations(x1), rearrange_activations(x2)

    q1, _ = torch.qr(x1_flat)
    q2, _ = torch.qr(x2_flat)

    return (torch.norm(q2.T @ q1)) ** 2 / q1.shape[1]
//  [python]
def cca_torch(x1, x2):
    x1_flat, x2_flat = rearrange_activations(x1), rearrange_activations(x2)

    q1, _ = torch.linalg.qr(x1_flat)
    q2, _ = torch.linalg.qr(x2_flat)

    return (torch.norm(q2.T @ q1)) ** 2 / q1.shape[1]
//  [python]
def __init__(self):
        super(Invertible_1x1_Conv, self).__init__()
        assert hp.Decoder.Num_Split % 2 == 0

        weight = torch.qr(torch.FloatTensor(
            hp.Decoder.Num_Split,
            hp.Decoder.Num_Split
            ).normal_())[0]
        if torch.det(weight) < 0:
            weight[:, 0] = -weight[:, 0]

        self.weight = torch.nn.Parameter(weight)
//  [python]
def __init__(self):
        super(Invertible_1x1_Conv, self).__init__()
        assert hp.Decoder.Num_Split % 2 == 0

        weight = torch.linalg.qr(torch.FloatTensor(
            hp.Decoder.Num_Split,
            hp.Decoder.Num_Split
            ).normal_())[0]
        if torch.det(weight) < 0:
            weight[:, 0] = -weight[:, 0]

        self.weight = torch.nn.Parameter(weight)
//  [python]
def _init_cache_for_constant_diag(self, eye, batch_shape, n, k):
        # We can factor out the noise for for both QR and solves.
        self._noise = self._noise.narrow(-2, 0, 1)
        self._q_cache, self._r_cache = torch.qr(torch.cat((self._piv_chol_self, self._noise.sqrt() * eye), dim=-2))
        self._q_cache = self._q_cache[..., :n, :]

        # Use the matrix determinant lemma for the logdet, using the fact that R'R = L_k'L_k + s*I
        logdet = self._r_cache.diagonal(dim1=-1, dim2=-2).abs().log().sum(-1).mul(2)
        logdet = logdet + (n - k) * self._noise.squeeze(-2).squeeze(-1).log()
        self._precond_logdet_cache = logdet.view(*batch_shape) if len(batch_shape) else logdet.squeeze()
//  [python]
def _init_cache_for_constant_diag(self, eye, batch_shape, n, k):
        # We can factor out the noise for for both QR and solves.
        self._noise = self._noise.narrow(-2, 0, 1)
        self._q_cache, self._r_cache = torch.linalg.qr(torch.cat((self._piv_chol_self, self._noise.sqrt() * eye), dim=-2))
        self._q_cache = self._q_cache[..., :n, :]

        # Use the matrix determinant lemma for the logdet, using the fact that R'R = L_k'L_k + s*I
        logdet = self._r_cache.diagonal(dim1=-1, dim2=-2).abs().log().sum(-1).mul(2)
        logdet = logdet + (n - k) * self._noise.squeeze(-2).squeeze(-1).log()
        self._precond_logdet_cache = logdet.view(*batch_shape) if len(batch_shape) else logdet.squeeze()
//  [python]
def __init__(self, size, kernel_fun=nn.ReLU(), **kwargs):
        super().__init__()
        self.dim, _ = size
        self.kernel_fun = kernel_fun

        proj = torch.randn(self.dim, self.dim)
        orth_proj, _ = torch.qr(proj)

        self.register_buffer("orth_proj", orth_proj)
//  [python]
def __init__(self, size, kernel_fun=nn.ReLU(), **kwargs):
        super().__init__()
        self.dim, _ = size
        self.kernel_fun = kernel_fun

        proj = torch.randn(self.dim, self.dim)
        orth_proj, _ = torch.linalg.qr(proj)

        self.register_buffer("orth_proj", orth_proj)
//  [python]
def _init_cache_for_non_constant_diag(self, eye, batch_shape, n):
        # With non-constant diagonals, we cant factor out the noise as easily
        self._q_cache, self._r_cache = torch.qr(torch.cat((self._piv_chol_self / self._noise.sqrt(), eye), dim=-2))
        self._q_cache = self._q_cache[..., :n, :] / self._noise.sqrt()

        # Use the matrix determinant lemma for the logdet, using the fact that R'R = L_k'L_k + s*I
        logdet = self._r_cache.diagonal(dim1=-1, dim2=-2).abs().log().sum(-1).mul(2)
        logdet -= (1.0 / self._noise).log().sum([-1, -2])
        self._precond_logdet_cache = logdet.view(*batch_shape) if len(batch_shape) else logdet.squeeze()
//  [python]
def _init_cache_for_non_constant_diag(self, eye, batch_shape, n):
        # With non-constant diagonals, we cant factor out the noise as easily
        self._q_cache, self._r_cache = torch.linalg.qr(torch.cat((self._piv_chol_self / self._noise.sqrt(), eye), dim=-2))
        self._q_cache = self._q_cache[..., :n, :] / self._noise.sqrt()

        # Use the matrix determinant lemma for the logdet, using the fact that R'R = L_k'L_k + s*I
        logdet = self._r_cache.diagonal(dim1=-1, dim2=-2).abs().log().sum(-1).mul(2)
        logdet -= (1.0 / self._noise).log().sum([-1, -2])
        self._precond_logdet_cache = logdet.view(*batch_shape) if len(batch_shape) else logdet.squeeze()
//  [python]
def __init__(self, num_channels, LU_decomposed=False):
        super().__init__()
        w_shape = [num_channels, num_channels]
        w_init = torch.qr(torch.randn(*w_shape))[0]

        if not LU_decomposed:
            self.weight = nn.Parameter(torch.Tensor(w_init))
        else:
            p, lower, upper = torch.lu_unpack(*torch.lu(w_init))
            s = torch.diag(upper)
            sign_s = torch.sign(s)
            log_s = torch.log(torch.abs(s))
            upper = torch.triu(upper, 1)
            l_mask = torch.tril(torch.ones(w_shape), -1)
            eye = torch.eye(*w_shape)

            self.register_buffer("p", p)
            self.register_buffer("sign_s", sign_s)
            self.lower = nn.Parameter(lower)
            self.log_s = nn.Parameter(log_s)
            self.upper = nn.Parameter(upper)
            self.l_mask = l_mask
            self.eye = eye

        self.w_shape = w_shape
        self.LU_decomposed = LU_decomposed
//  [python]
def __init__(self, num_channels, LU_decomposed=False):
        super().__init__()
        w_shape = [num_channels, num_channels]
        w_init = torch.linalg.qr(torch.randn(*w_shape))[0]

        if not LU_decomposed:
            self.weight = nn.Parameter(torch.Tensor(w_init))
        else:
            p, lower, upper = torch.lu_unpack(*torch.lu(w_init))
            s = torch.diag(upper)
            sign_s = torch.sign(s)
            log_s = torch.log(torch.abs(s))
            upper = torch.triu(upper, 1)
            l_mask = torch.tril(torch.ones(w_shape), -1)
            eye = torch.eye(*w_shape)

            self.register_buffer("p", p)
            self.register_buffer("sign_s", sign_s)
            self.lower = nn.Parameter(lower)
            self.log_s = nn.Parameter(log_s)
            self.upper = nn.Parameter(upper)
            self.l_mask = l_mask
            self.eye = eye

        self.w_shape = w_shape
        self.LU_decomposed = LU_decomposed
//  [python]
def __init__(self, x_size, p):
        super(random_basis, self).__init__()
        n_ch , im_d1, im_d2 = x_size
        self.x_size = x_size
        self.U, _ = torch.qr(torch.randn(int(np.prod(x_size)),int(np.prod(x_size)*p) ))
        if torch.cuda.is_available():
            self.U = self.U.cuda()
//  [python]
def __init__(self, x_size, p):
        super(random_basis, self).__init__()
        n_ch , im_d1, im_d2 = x_size
        self.x_size = x_size
        self.U, _ = torch.linalg.qr(torch.randn(int(np.prod(x_size)),int(np.prod(x_size)*p) ))
        if torch.cuda.is_available():
            self.U = self.U.cuda()
//  [python]
def fit(self, sparse_thetas: TensorList, time_derivs: TensorList) -> TensorList:
        """Calculates the coefficients of the constraint using the QR decomposition for every pair
        of sparse feature matrix and time derivative.

        Args:
            sparse_thetas (TensorList): List containing the sparse feature tensors of size (n_samples, n_active_features).
            time_derivs (TensorList): List containing the time derivatives of size (n_samples, n_outputs).

        Returns:
            (TensorList): List of calculated coefficients of size [(n_active_features, 1) x n_outputs].
        """
        coeff_vectors = []
        for theta, dt in zip(sparse_thetas, time_derivs):
            Q, R = torch.qr(theta)  # solution of lst. sq. by QR decomp.
            coeff_vectors.append(torch.inverse(R) @ Q.T @ dt)
        return coeff_vectors
//  [python]
def fit(self, sparse_thetas: TensorList, time_derivs: TensorList) -> TensorList:
        """Calculates the coefficients of the constraint using the QR decomposition for every pair
        of sparse feature matrix and time derivative.

        Args:
            sparse_thetas (TensorList): List containing the sparse feature tensors of size (n_samples, n_active_features).
            time_derivs (TensorList): List containing the time derivatives of size (n_samples, n_outputs).

        Returns:
            (TensorList): List of calculated coefficients of size [(n_active_features, 1) x n_outputs].
        """
        coeff_vectors = []
        for theta, dt in zip(sparse_thetas, time_derivs):
            Q, R = torch.linalg.qr(theta)  # solution of lst. sq. by QR decomp.
            coeff_vectors.append(torch.inverse(R) @ Q.T @ dt)
        return coeff_vectors
//  [python]
def __init__(self, c):
        super().__init__()
        self.conv = torch.nn.Conv1d(c, c, kernel_size=1, stride=1, padding=0, bias=False)

        # Sample a random orthonormal matrix to initialize weights
        W = torch.qr(torch.FloatTensor(c, c).normal_())[0]

        # Ensure determinant is 1.0 not -1.0
        if torch.det(W) < 0:
            W[:, 0] = -1 * W[:, 0]
        W = W.view(c, c, 1)
        self.conv.weight.data = W
//  [python]
def __init__(self, c):
        super().__init__()
        self.conv = torch.nn.Conv1d(c, c, kernel_size=1, stride=1, padding=0, bias=False)

        # Sample a random orthonormal matrix to initialize weights
        W = torch.linalg.qr(torch.FloatTensor(c, c).normal_())[0]

        # Ensure determinant is 1.0 not -1.0
        if torch.det(W) < 0:
            W[:, 0] = -1 * W[:, 0]
        W = W.view(c, c, 1)
        self.conv.weight.data = W
//  [python]
def qr(matrix, rhs):
    q, r = torch.qr(matrix)
    y = torch.matmul(q.T, rhs)
    return torch.triangular_solve(r, y).solution
//  [python]
def qr(matrix, rhs):
    q, r = torch.linalg.qr(matrix)
    y = torch.matmul(q.T, rhs)
    return torch.triangular_solve(r, y).solution
//  [python]
def OrthogonalRandomFeature(self):
        n = self.n_features//self.depth
        remainder = self.n_features%self.depth
        orthogonal_features = []
        for _ in range(n):
            normal_feature = torch.rand(self.depth, self.depth)
            orthogonal_feature, _ = torch.qr(normal_feature)
            orthogonal_features.append(orthogonal_feature)
        
        if remainder > 0 :
            normal_feature = torch.rand(self.depth, self.depth)
            orthogonal_feature, _ = torch.qr(normal_feature)
            orthogonal_features.append(orthogonal_feature[0: remainder])
        
        orthogonal_features = torch.cat(orthogonal_features)
        mutilplier =  torch.randn(self.n_features, self.depth).norm(dim=1)
        final_features = torch.matmul(torch.diag(mutilplier), orthogonal_features)

        return final_features
//  [python]
def OrthogonalRandomFeature(self):
        n = self.n_features//self.depth
        remainder = self.n_features%self.depth
        orthogonal_features = []
        for _ in range(n):
            normal_feature = torch.rand(self.depth, self.depth)
            orthogonal_feature, _ = torch.linalg.qr(normal_feature)
            orthogonal_features.append(orthogonal_feature)
        
        if remainder > 0 :
            normal_feature = torch.rand(self.depth, self.depth)
            orthogonal_feature, _ = torch.linalg.qr(normal_feature)
            orthogonal_features.append(orthogonal_feature[0: remainder])
        
        orthogonal_features = torch.cat(orthogonal_features)
        mutilplier =  torch.randn(self.n_features, self.depth).norm(dim=1)
        final_features = torch.matmul(torch.diag(mutilplier), orthogonal_features)

        return final_features
//  [python]
def __init__(self, c):
        super(Invertible1x1Conv, self).__init__()
        self.conv = nn.Conv1d(c, c, kernel_size=1, stride=1, padding=0,
                                    bias=False)
        
        # Sample a random orthonormal matrix to initialize weights
        W = torch.qr(torch.FloatTensor(c, c).normal_())[0]
        
        # Ensure determinant is 1.0 not -1.0
        if torch.det(W) < 0:
            W[:,0] = -1*W[:,0]
        W = W.view(c, c, 1)
        self.conv.weight.data = W
//  [python]
def __init__(self, c):
        super(Invertible1x1Conv, self).__init__()
        self.conv = nn.Conv1d(c, c, kernel_size=1, stride=1, padding=0,
                                    bias=False)
        
        # Sample a random orthonormal matrix to initialize weights
        W = torch.linalg.qr(torch.FloatTensor(c, c).normal_())[0]
        
        # Ensure determinant is 1.0 not -1.0
        if torch.det(W) < 0:
            W[:,0] = -1*W[:,0]
        W = W.view(c, c, 1)
        self.conv.weight.data = W
//  [python]
def __init__(self, c):
        super(Invertible1x1Conv, self).__init__()
        self.conv = torch.nn.Conv1d(
            c, c, kernel_size=1, stride=1, padding=0, bias=False
        )

        # Sample a random orthonormal matrix to initialize weights
        W = torch.qr(torch.FloatTensor(c, c).normal_())[0]

        # Ensure determinant is 1.0 not -1.0
        if torch.det(W) < 0:
            W[:, 0] = -1 * W[:, 0]
        W = W.view(c, c, 1)
        self.conv.weight.data = W
//  [python]
def __init__(self, c):
        super(Invertible1x1Conv, self).__init__()
        self.conv = torch.nn.Conv1d(
            c, c, kernel_size=1, stride=1, padding=0, bias=False
        )

        # Sample a random orthonormal matrix to initialize weights
        W = torch.linalg.qr(torch.FloatTensor(c, c).normal_())[0]

        # Ensure determinant is 1.0 not -1.0
        if torch.det(W) < 0:
            W[:, 0] = -1 * W[:, 0]
        W = W.view(c, c, 1)
        self.conv.weight.data = W
//  [python]
def __init__(self, channels, n_split=4, no_jacobian=False, **kwargs):
        super().__init__()
        assert n_split % 2 == 0
        self.channels = channels
        self.n_split = n_split
        self.no_jacobian = no_jacobian

        w_init = torch.qr(torch.FloatTensor(self.n_split, self.n_split).normal_())[0]
        if torch.det(w_init) < 0:
            w_init[:, 0] = -1 * w_init[:, 0]
        self.weight = nn.Parameter(w_init)
//  [python]
def __init__(self, channels, n_split=4, no_jacobian=False, **kwargs):
        super().__init__()
        assert n_split % 2 == 0
        self.channels = channels
        self.n_split = n_split
        self.no_jacobian = no_jacobian

        w_init = torch.linalg.qr(torch.FloatTensor(self.n_split, self.n_split).normal_())[0]
        if torch.det(w_init) < 0:
            w_init[:, 0] = -1 * w_init[:, 0]
        self.weight = nn.Parameter(w_init)
//  [python]
def test_ormqr(self):
        mat1 = torch.randn(7, 7)
        mat2 = torch.randn(7, 7)
        q, r = torch.qr(mat1)
        m, tau = torch.geqrf(mat1)
        out_holder = torch.empty_like(mat1)

        res1 = torch.mm(q, mat2)
        res2 = torch.ormqr(m, tau, mat2, left=True, transpose=False)
        torch.ormqr(m, tau, mat2, out=out_holder)
        self.assertEqual(res1, res2)
        self.assertEqual(res2, out_holder)

        res1 = torch.mm(mat2, q)
        res2 = torch.ormqr(m, tau, mat2, left=False, transpose=False)
        torch.ormqr(m, tau, mat2, left=False, transpose=False, out=out_holder)
        self.assertEqual(res1, res2)
        self.assertEqual(res2, out_holder)

        res1 = torch.mm(q.t(), mat2)
        res2 = torch.ormqr(m, tau, mat2, left=True, transpose=True)
        torch.ormqr(m, tau, mat2, left=True, transpose=True, out=out_holder)
        self.assertEqual(res1, res2)
        self.assertEqual(res2, out_holder)

        res1 = torch.mm(mat2, q.t())
        res2 = torch.ormqr(m, tau, mat2, left=False, transpose=True)
        torch.ormqr(m, tau, mat2, left=False, transpose=True, out=out_holder)
        self.assertEqual(res1, res2)
        self.assertEqual(res2, out_holder)
//  [python]
def test_ormqr(self):
        mat1 = torch.randn(7, 7)
        mat2 = torch.randn(7, 7)
        q, r = torch.linalg.qr(mat1)
        m, tau = torch.geqrf(mat1)
        out_holder = torch.empty_like(mat1)

        res1 = torch.mm(q, mat2)
        res2 = torch.ormqr(m, tau, mat2, left=True, transpose=False)
        torch.ormqr(m, tau, mat2, out=out_holder)
        self.assertEqual(res1, res2)
        self.assertEqual(res2, out_holder)

        res1 = torch.mm(mat2, q)
        res2 = torch.ormqr(m, tau, mat2, left=False, transpose=False)
        torch.ormqr(m, tau, mat2, left=False, transpose=False, out=out_holder)
        self.assertEqual(res1, res2)
        self.assertEqual(res2, out_holder)

        res1 = torch.mm(q.t(), mat2)
        res2 = torch.ormqr(m, tau, mat2, left=True, transpose=True)
        torch.ormqr(m, tau, mat2, left=True, transpose=True, out=out_holder)
        self.assertEqual(res1, res2)
        self.assertEqual(res2, out_holder)

        res1 = torch.mm(mat2, q.t())
        res2 = torch.ormqr(m, tau, mat2, left=False, transpose=True)
        torch.ormqr(m, tau, mat2, left=False, transpose=True, out=out_holder)
        self.assertEqual(res1, res2)
        self.assertEqual(res2, out_holder)
//  [python]
def orthogonal(tensor, gain = 1):
    if tensor.ndimension() < 2:
        raise ValueError("Only tensors with 2 or more dimensions are suppored")
    
    rows = tensor.size(0)
    cols = tensor[0].numel()

    flattened = torch.Tensor(rows, cols).normal_(0, 1)

    if rows < cols:
        flattened.t_()


    q, r = torch.qr(flattened)
    d = torch.diag(r, 0)
    ph = d.sign()

    q *= ph.expand_as(q)

    if rows < cols:
        q.t_()

    tensor.view_as(q).copy_(q)
    tensor.mul_(gain)
    return tensor
//  [python]
def orthogonal(tensor, gain = 1):
    if tensor.ndimension() < 2:
        raise ValueError("Only tensors with 2 or more dimensions are suppored")
    
    rows = tensor.size(0)
    cols = tensor[0].numel()

    flattened = torch.Tensor(rows, cols).normal_(0, 1)

    if rows < cols:
        flattened.t_()


    q, r = torch.linalg.qr(flattened)
    d = torch.diag(r, 0)
    ph = d.sign()

    q *= ph.expand_as(q)

    if rows < cols:
        q.t_()

    tensor.view_as(q).copy_(q)
    tensor.mul_(gain)
    return tensor
//  [python]
def __init__(self, in_channel):
    super().__init__()

    weight = torch.randn(in_channel, in_channel)
    q, _ = torch.qr(weight)
    weight = q.unsqueeze(2).unsqueeze(3)
    self.weight = nn.Parameter(weight)
//  [python]
def __init__(self, in_channel):
    super().__init__()

    weight = torch.randn(in_channel, in_channel)
    q, _ = torch.linalg.qr(weight)
    weight = q.unsqueeze(2).unsqueeze(3)
    self.weight = nn.Parameter(weight)
//  [python]
def random_ortho(n, m):
    q, _ = torch.qr(torch.randn(n, m))
    return q
//  [python]
def random_ortho(n, m):
    q, _ = torch.linalg.qr(torch.randn(n, m))
    return q
//  [python]
def __init__(self, in_features):
        super().__init__()
        self.in_features = in_features

        weight = torch.qr(torch.randn(in_features, in_features))[0].contiguous()
        self.weight = nn.Parameter(weight)

        self.register_buffer("inv_weight", torch.inverse(self.weight))
//  [python]
def __init__(self, in_features):
        super().__init__()
        self.in_features = in_features

        weight = torch.linalg.qr(torch.randn(in_features, in_features))[0].contiguous()
        self.weight = nn.Parameter(weight)

        self.register_buffer("inv_weight", torch.inverse(self.weight))
//  [python]
def test_caffe2_aten_fallback(self):
        class ModelWithAtenNotONNXOp(nn.Module):
            def forward(self, x, y):
                abcd = x + y
                defg = torch.qr(abcd)
                return defg

        x = torch.rand(3, 4)
        y = torch.rand(3, 4)
        torch.onnx.export_to_pretty_string(
            ModelWithAtenNotONNXOp(),
            (x, y),
            add_node_names=False,
            do_constant_folding=False,
            operator_export_type=OperatorExportTypes.ONNX_ATEN_FALLBACK,
        )
//  [python]
def test_caffe2_aten_fallback(self):
        class ModelWithAtenNotONNXOp(nn.Module):
            def forward(self, x, y):
                abcd = x + y
                defg = torch.linalg.qr(abcd)
                return defg

        x = torch.rand(3, 4)
        y = torch.rand(3, 4)
        torch.onnx.export_to_pretty_string(
            ModelWithAtenNotONNXOp(),
            (x, y),
            add_node_names=False,
            do_constant_folding=False,
            operator_export_type=OperatorExportTypes.ONNX_ATEN_FALLBACK,
        )
//  [python]
def test_aten_fallback(self):
        class ModelWithAtenNotONNXOp(nn.Module):
            def forward(self, x, y):
                abcd = x + y
                defg = torch.qr(abcd)
                return defg

        x = torch.rand(3, 4)
        y = torch.rand(3, 4)
        torch.onnx.export_to_pretty_string(
            ModelWithAtenNotONNXOp(),
            (x, y),
            add_node_names=False,
            do_constant_folding=False,
            operator_export_type=OperatorExportTypes.ONNX_ATEN_FALLBACK,
            # support for linalg.qr was added in later op set versions.
            opset_version=9,
        )
//  [python]
def test_aten_fallback(self):
        class ModelWithAtenNotONNXOp(nn.Module):
            def forward(self, x, y):
                abcd = x + y
                defg = torch.linalg.qr(abcd)
                return defg

        x = torch.rand(3, 4)
        y = torch.rand(3, 4)
        torch.onnx.export_to_pretty_string(
            ModelWithAtenNotONNXOp(),
            (x, y),
            add_node_names=False,
            do_constant_folding=False,
            operator_export_type=OperatorExportTypes.ONNX_ATEN_FALLBACK,
            # support for linalg.qr was added in later op set versions.
            opset_version=9,
        )
//  [python]
def orthogonal_matrix_chunk(cols, qr_uniform_q = False, device = None):
    unstructured_block = torch.randn((cols, cols), device = device)
    q, r = torch.qr(unstructured_block.cpu())
    q, r = map(lambda t: t.to(device), (q, r))

    # proposed by @Parskatt
    # to make sure Q is uniform https://arxiv.org/pdf/math-ph/0609050.pdf
    if qr_uniform_q:
        d = torch.diag(r, 0)
        q *= d.sign()
    return q.t()
//  [python]
def orthogonal_matrix_chunk(cols, qr_uniform_q = False, device = None):
    unstructured_block = torch.randn((cols, cols), device = device)
    q, r = torch.linalg.qr(unstructured_block.cpu(), mode='reduced')
    q, r = map(lambda t: t.to(device), (q, r))

    # proposed by @Parskatt
    # to make sure Q is uniform https://arxiv.org/pdf/math-ph/0609050.pdf
    if qr_uniform_q:
        d = torch.diag(r, 0)
        q *= d.sign()
    return q.t()
//  [python]
def Qr(a):
    # v0.3 OK
    """
    The function performs the qr decomposition

        :math:`a = q \cdot r`

    to the input UniTensor. The UniTensor should be rank-2, untagged. each bond's dim should be >=2.


    Args:

        a : UniTensor[untagged], it is required to be a non-diagonal rank-2 tensor. If pass a non rank-2 tensor or diagonal matrix, it will throw Exception.

    Return:

        q , r

        q : UniTensor[regular], rank-2, 1 inbond 1 outbond, the unitary matrix

        r : UniTensor[regular], rank-2, 1 inbond 1 outbond, the upper triangular matrix

    """
    if isinstance(a,UniTensor):

        ## Qnum_ipoint
        if a.is_symm:
            raise Exception("Qr(a)","don't support symm tensor. GetBlock() first")

        if a.is_diag:
            raise Exception("Qr(UniTensor)","[Aboart] Currently not support diagonal tensors.")

        if a.braket is not None:
            raise Exception("Qr(UniTensor)","Can only accept [untagged] tensor")

        if a.rowrank != 1:
            raise Exception("Qr(UniTensor)","Should have 1 in-bond, 1 out-bond")

        q, r = torch.qr(a.Storage)

        tmp = np.argwhere(a.labels<0)
        if len(tmp) == 0:
            tmp = 0
        else:
            tmp = np.min(tmp)

        tq = UniTensor(bonds =[Bond(q.shape[0]),Bond(q.shape[1])],\
                      rowrank=1,\
                      labels=[a.labels[0],tmp-1],\
                      check=False)
        tq._mac(torch_tensor=q)

        tr = UniTensor(bonds =[Bond(r.shape[0]),Bond(r.shape[1])],\
                      rowrank=1,\
                      labels=[tq.labels[1],a.labels[1]],\
                      check=False)
        tr._mac(torch_tensor = r)

        return tq,tr
    else:
        raise Exception("Qr(UniTensor)","[ERROR] Qr can only accept UniTensor")
//  [python]
def Qr(a):
    # v0.3 OK
    """
    The function performs the qr decomposition

        :math:`a = q \cdot r`

    to the input UniTensor. The UniTensor should be rank-2, untagged. each bond's dim should be >=2.


    Args:

        a : UniTensor[untagged], it is required to be a non-diagonal rank-2 tensor. If pass a non rank-2 tensor or diagonal matrix, it will throw Exception.

    Return:

        q , r

        q : UniTensor[regular], rank-2, 1 inbond 1 outbond, the unitary matrix

        r : UniTensor[regular], rank-2, 1 inbond 1 outbond, the upper triangular matrix

    """
    if isinstance(a,UniTensor):

        ## Qnum_ipoint
        if a.is_symm:
            raise Exception("Qr(a)","don't support symm tensor. GetBlock() first")

        if a.is_diag:
            raise Exception("Qr(UniTensor)","[Aboart] Currently not support diagonal tensors.")

        if a.braket is not None:
            raise Exception("Qr(UniTensor)","Can only accept [untagged] tensor")

        if a.rowrank != 1:
            raise Exception("Qr(UniTensor)","Should have 1 in-bond, 1 out-bond")

        q, r = torch.linalg.qr(a.Storage)

        tmp = np.argwhere(a.labels<0)
        if len(tmp) == 0:
            tmp = 0
        else:
            tmp = np.min(tmp)

        tq = UniTensor(bonds =[Bond(q.shape[0]),Bond(q.shape[1])],\
                      rowrank=1,\
                      labels=[a.labels[0],tmp-1],\
                      check=False)
        tq._mac(torch_tensor=q)

        tr = UniTensor(bonds =[Bond(r.shape[0]),Bond(r.shape[1])],\
                      rowrank=1,\
                      labels=[tq.labels[1],a.labels[1]],\
                      check=False)
        tr._mac(torch_tensor = r)

        return tq,tr
    else:
        raise Exception("Qr(UniTensor)","[ERROR] Qr can only accept UniTensor")
//  [python]
def random_features(rows: int, cols: int, stddev: float = 0.05, orthogonal: bool = False, random_norm: bool = True) -> T:
    if orthogonal:
        cols_sampled, c = 0, []
        while cols_sampled < cols:
            # qr only returns orthogonal Q's as an (N, N) square matrix
            c.append(stddev * torch.qr(torch.randn(rows, rows, requires_grad=False))[0])
            cols_sampled += rows

        w = torch.cat(c, dim=-1)[:, :cols]

        # if not random norms for the columns, scale each norm column by the expected norm of each column.
        # https://github.com/google/edward2/blob/720d7985a889362d421053965b6c528390557b05/edward2/tensorflow/initializers.py#L814
        if not random_norm:
            return w * np.sqrt(rows)  # type: ignore

        col_norms = (torch.randn(rows, cols) ** 2).sum(dim=0).sqrt()
        return w * col_norms  # type: ignore
    return stddev * torch.randn(rows, cols, requires_grad=False)
//  [python]
def random_features(rows: int, cols: int, stddev: float = 0.05, orthogonal: bool = False, random_norm: bool = True) -> T:
    if orthogonal:
        cols_sampled, c = 0, []
        while cols_sampled < cols:
            # qr only returns orthogonal Q's as an (N, N) square matrix
            c.append(stddev * torch.linalg.qr(torch.randn(rows, rows, requires_grad=False), mode="complete")[0])
            cols_sampled += rows

        w = torch.cat(c, dim=-1)[:, :cols]

        # if not random norms for the columns, scale each norm column by the expected norm of each column.
        # https://github.com/google/edward2/blob/720d7985a889362d421053965b6c528390557b05/edward2/tensorflow/initializers.py#L814
        if not random_norm:
            return w * np.sqrt(rows)  # type: ignore

        col_norms = (torch.randn(rows, cols) ** 2).sum(dim=0).sqrt()
        return w * col_norms  # type: ignore
    return stddev * torch.randn(rows, cols, requires_grad=False)
//  [python]
def lstsq(b, A, method='qr', lam=1e-6, eps=1e-3):
    if method == 'qr':
        Q, R = torch.qr(A.T)
        X = b.T @ torch.pinverse(R) @ Q.T

        return [X.T]
    elif method == 'cvxpylayers':
        from cvxpylayers.torch import CvxpyLayer
        assert b.shape[0] == A.shape[0]

        m, n = A.shape
        m, k = b.shape

        Acp = cp.Parameter((m, n))
        bcp = cp.Parameter((m, k))
        x = cp.Variable((n, k))
        obj = cp.sum_squares(Acp @ x - bcp) + lam * cp.pnorm(x, p=2)**2
        prob = cp.Problem(cp.Minimize(obj))
        prob_th = CvxpyLayer(prob, [Acp, bcp], [x])

        return prob_th(A, b, solver_args={'eps': eps})
    else:
        raise ValueError('Wrong value of method parameter, only qr and cvxpylayers are supported')
//  [python]
def lstsq(b, A, method='qr', lam=1e-6, eps=1e-3):
    if method == 'qr':
        Q, R = torch.linalg.qr(A.T)
        X = b.T @ torch.linalg.pinv(R) @ Q.T

        return [X.T]
    elif method == 'cvxpylayers':
        from cvxpylayers.torch import CvxpyLayer
        assert b.shape[0] == A.shape[0]

        m, n = A.shape
        m, k = b.shape

        Acp = cp.Parameter((m, n))
        bcp = cp.Parameter((m, k))
        x = cp.Variable((n, k))
        obj = cp.sum_squares(Acp @ x - bcp) + lam * cp.pnorm(x, p=2)**2
        prob = cp.Problem(cp.Minimize(obj))
        prob_th = CvxpyLayer(prob, [Acp, bcp], [x])

        return prob_th(A, b, solver_args={'eps': eps})
    else:
        raise ValueError('Wrong value of method parameter, only qr and cvxpylayers are supported')
//  [python]
def orthogonal_matrix_chunk(cols, device=None):
    unstructured_block = torch.randn((cols, cols), device=device)
    q, r = torch.qr(unstructured_block)
    return q.t()
//  [python]
def orthogonal_matrix_chunk(cols, device=None):
    unstructured_block = torch.randn((cols, cols), device=device)
    q, r = torch.linalg.qr(unstructured_block)
    return q.t()