code: def test_make_linear_constraints(self):
      # equality constraints, 1d indices
      indices = torch.tensor(
          [1, 2], dtype=torch.long, device=self.device
      )
      for dtype, shapeX in product(
          (torch.float, torch.double),
          (torch.Size([3, 2, 4]), torch.Size([2, 4])),
      ):
          coefficients = torch.tensor(
              [1.0, 2.0], dtype=dtype, device=self.device
          )
          constraints = _make_linear_constraints(
              indices=indices,
              coefficients=coefficients,
              rhs=1.0,
              shapeX=shapeX,
              eq=True,
          )
          self.assertTrue(
              all(
                  set(c.keys()) == {"fun", "jac", "type"}
                  for c in constraints
              )
          )
          self.assertTrue(all(c["type"] == "eq" for c in constraints))
          self.assertEqual(len(constraints), shapeX[:-1].numel())
          x = np.random.rand(shapeX.numel())
          self.assertEqual(
              constraints[0]["fun"](x), x[1] + 2 * x[2] - 1.0
          )
          jac_exp = np.zeros(shapeX.numel())
          jac_exp[[1, 2]] = [1, 2]
          self.assertTrue(
              np.allclose(constraints[0]["jac"](x), jac_exp)
          )
          self.assertEqual(
              constraints[-1]["fun"](x), x[-3] + 2 * x[-2] - 1.0
          )
          jac_exp = np.zeros(shapeX.numel())
          jac_exp[[-3, -2]] = [1, 2]
          self.assertTrue(
              np.allclose(constraints[-1]["jac"](x), jac_exp)
          )
  
      # inequality constraints, 1d indices
      for shapeX in [torch.Size([1, 1, 2]), torch.Size([1, 2])]:
          lcs = _make_linear_constraints(
              indices=torch.tensor([1]),
              coefficients=torch.tensor([1.0]),
              rhs=1.0,
              shapeX=shapeX,
              eq=False,
          )
          self.assertEqual(len(lcs), 1)
          self.assertEqual(lcs[0]["type"], "ineq")
  
      # constraint across q-batch (2d indics), equality constraint
      indices = torch.tensor(
          [[0, 3], [1, 2]], dtype=torch.long, device=self.device
      )
  
      for dtype, shapeX in product(
          (torch.float, torch.double),
          (torch.Size([3, 2, 4]), torch.Size([2, 4])),
      ):
          q, d = shapeX[-2:]
          b = 1 if len(shapeX) == 2 else shapeX[0]
          coefficients = torch.tensor(
              [1.0, 2.0], dtype=dtype, device=self.device
          )
          constraints = _make_linear_constraints(
              indices=indices,
              coefficients=coefficients,
              rhs=1.0,
              shapeX=shapeX,
              eq=True,
          )
          self.assertTrue(
              all(
                  set(c.keys()) == {"fun", "jac", "type"}
                  for c in constraints
              )
          )
          self.assertTrue(all(c["type"] == "eq" for c in constraints))
          self.assertEqual(len(constraints), b)
          x = np.random.rand(shapeX.numel())
          offsets = [q * d, d]
          # rule is [i, j, k] is i * offset[0] + j * offset[1] + k
          for i in range(b):
              pos1 = i * offsets[0] + 3
              pos2 = i * offsets[0] + 1 * offsets[1] + 2
              self.assertEqual(
                  constraints[i]["fun"](x), x[pos1] + 2 * x[pos2] - 1.0
              )
              jac_exp = np.zeros(shapeX.numel())
              jac_exp[[pos1, pos2]] = [1, 2]
              self.assertTrue(
                  np.allclose(constraints[i]["jac"](x), jac_exp)
              )
      # make sure error is raised for scalar tensors
      with self.assertRaises(ValueError):
          constraints = _make_linear_constraints(
              indices=torch.tensor(0),
              coefficients=torch.tensor([1.0]),
              rhs=1.0,
              shapeX=torch.Size([1, 1, 2]),
              eq=False,
          )
      # test that len(shapeX) < 2 raises an error
      with self.assertRaises(UnsupportedError):
          _make_linear_constraints(
              shapeX=torch.Size([2]),
              indices=indices,
              coefficients=coefficients,
              rhs=0.0,
          )
  
imports: from itertools import product
  from typing import Callable
  import numpy
  import torch
  from botorch.exceptions.errors import CandidateGenerationError, UnsupportedError
  from botorch.optim.parameter_constraints import _arrayify, _generate_unfixed_lin_constraints, _generate_unfixed_nonlin_constraints, _make_linear_constraints, _make_nonlinear_constraints, eval_lin_constraint, lin_constraint_jac, make_scipy_bounds, make_scipy_linear_constraints, make_scipy_nonlinear_inequality_constraints, nonlinear_constraint_is_feasible
  from botorch.utils.testing import BotorchTestCase
  from scipy.optimize import Bounds
label_desc: Use image node_id 6 for calling the TestParameterConstraints obj's underlying member method code with example usage: obj.test_make_linear_constraints() without return types