class_docstr: Linear Elliptical Slice Sampler.
  
  Ideas:
  - Add batch support, broadcasting over parallel chains.
  - Optimize computations if possible, potentially with torch.compile.
  - Extend fixed features constraint to general linear equality constraints.
class_docstr_tok: ["Linear","Elliptical","Slice","Sampler",".","Ideas",":","-","Add","batch","support",",","broadcasting","over","parallel","chains",".","-","Optimize","computations","if","possible",",","potentially","with","torch.compile",".","-","Extend","fixed","features","constraint","to","general","linear","equality","constraints","."]
docstr: Compute all of the up to 2*n_ineq_con intersections of the ellipse
  and the linear constraints.
  
  For background, see equation (2) in
  http://proceedings.mlr.press/v108/gessner20a/gessner20a.pdf
  
  Args:
      nu: A `d x 1`-dim tensor (the "new" direction, drawn from N(0, I)).
  
  Returns:
      An `M`-dim tensor, where `M <= 2 * n_ineq_con` (with `M = n_ineq_con`
      if all intermediate computations yield finite numbers).
docstr_tok: ["Compute","all","of","the","up","to","2","*","n_ineq_con","intersections","of","the","ellipse","and","the","linear","constraints",".","For","background",",","see","equation","(","2",")","in","http",":","\/\/proceedings.mlr.press\/v108\/gessner20a\/gessner20a.pdf","Args",":","nu",":","A","`","d","x","1","`","-dim","tensor","(","the","``","new","''","direction",",","drawn","from","N","(","0",",","I",")",")",".","Returns",":","An","`","M","`","-dim","tensor",",","where","`","M","<","=","2","*","n_ineq_con","`","(","with","`","M","=","n_ineq_con","`","if","all","intermediate","computations","yield","finite","numbers",")","."]
code: def _find_intersection_angles(self, nu: Tensor) -> Tensor:
      """Compute all of the up to 2*n_ineq_con intersections of the ellipse
      and the linear constraints.
  
      For background, see equation (2) in
      http://proceedings.mlr.press/v108/gessner20a/gessner20a.pdf
  
      Args:
          nu: A `d x 1`-dim tensor (the "new" direction, drawn from N(0, I)).
  
      Returns:
          An `M`-dim tensor, where `M <= 2 * n_ineq_con` (with `M = n_ineq_con`
          if all intermediate computations yield finite numbers).
      """
      # Compared to the implementation in https://github.com/alpiges/LinConGauss
      # we need to flip the sign of A b/c the original algorithm considers
      # A @ x + b >= 0 feasible, whereas we consider A @ x - b <= 0 feasible.
      g1 = -self._Az @ self._z
      g2 = -self._Az @ nu
      r = torch.sqrt(g1**2 + g2**2)
      phi = 2 * torch.atan(g2 / (r + g1)).squeeze()
  
      arg = -(self._bz / r).squeeze()
      # Write NaNs if there is no intersection
      arg = torch.where(torch.absolute(arg) <= 1, arg, self._nan)
      # Two solutions per linear constraint, shape of theta: (n_ineq_con, 2)
      acos_arg = torch.arccos(arg)
      theta = torch.stack((phi + acos_arg, phi - acos_arg), dim=-1)
      theta = theta[
          torch.isfinite(theta)
      ]  # shape: `n_ineq_con - num_not_finite`
      theta = torch.where(
          theta < 0, theta + _twopi, theta
      )  # in [0, 2*pi]
      return torch.sort(theta).values
  
imports: from __future__ import annotations
  import math
  from typing import List, Optional, Tuple, Union
  import torch
  from botorch.utils.sampling import PolytopeSampler
  from torch import Tensor
label_desc: Use image node_id 11 for calling the LinearEllipticalSliceSampler obj's underlying member method code with example usage: obj._find_intersection_angles(nu) and returns: torch