class_docstr: Don't perform any test, but provide the function to test the
  Rop to class that inherit from it.
class_docstr_tok: ["Do","n't","perform","any","test",",","but","provide","the","function","to","test","the","Rop","to","class","that","inherit","from","it","."]
docstr: Test the Rop/Lop when input is a matrix and the output is a vector
  
  :param y: the output variable of the op applied to self.mx
  :param out_shape: Used to generate a random tensor
                    corresponding to the evaluation point of the Rop
                    (i.e. the tensor with which you multiply the
                    Jacobian). It should be a tuple of ints.
  
  If the Op has more than 1 input, one of them must be mx, while
  others must be shared variables / constants. We will test only
  against the input self.mx, so you must call
  check_mat_rop_lop/check_rop_lop for the other inputs.
  
  We expect all inputs/outputs have dtype floatX.
  
  If you want to test an Op with an output matrix, add a sum
  after the Op you want to test.
docstr_tok: ["Test","the","Rop\/Lop","when","input","is","a","matrix","and","the","output","is","a","vector",":","param","y",":","the","output","variable","of","the","op","applied","to","self.mx",":","param","out_shape",":","Used","to","generate","a","random","tensor","corresponding","to","the","evaluation","point","of","the","Rop","(","i.e",".","the","tensor","with","which","you","multiply","the","Jacobian",")",".","It","should","be","a","tuple","of","ints",".","If","the","Op","has","more","than","1","input",",","one","of","them","must","be","mx",",","while","others","must","be","shared","variables","\/","constants",".","We","will","test","only","against","the","input","self.mx",",","so","you","must","call","check_mat_rop_lop\/check_rop_lop","for","the","other","inputs",".","We","expect","all","inputs\/outputs","have","dtype","floatX",".","If","you","want","to","test","an","Op","with","an","output","matrix",",","add","a","sum","after","the","Op","you","want","to","test","."]
code: def check_mat_rop_lop(self, y, out_shape):
      """
      Test the Rop/Lop when input is a matrix and the output is a vector
  
      :param y: the output variable of the op applied to self.mx
      :param out_shape: Used to generate a random tensor
                        corresponding to the evaluation point of the Rop
                        (i.e. the tensor with which you multiply the
                        Jacobian). It should be a tuple of ints.
  
      If the Op has more than 1 input, one of them must be mx, while
      others must be shared variables / constants. We will test only
      against the input self.mx, so you must call
      check_mat_rop_lop/check_rop_lop for the other inputs.
  
      We expect all inputs/outputs have dtype floatX.
  
      If you want to test an Op with an output matrix, add a sum
      after the Op you want to test.
      """
      vx = np.asarray(
          self.rng.uniform(size=self.mat_in_shape),
          pytensor.config.floatX,
      )
      vv = np.asarray(
          self.rng.uniform(size=self.mat_in_shape),
          pytensor.config.floatX,
      )
      yv = Rop(y, self.mx, self.mv)
      rop_f = function([self.mx, self.mv], yv, on_unused_input="ignore")
      sy, _ = pytensor.scan(
          lambda i, y, x, v: (grad(y[i], x) * v).sum(),
          sequences=pt.arange(y.shape[0]),
          non_sequences=[y, self.mx, self.mv],
      )
      scan_f = function(
          [self.mx, self.mv], sy, on_unused_input="ignore"
      )
  
      v1 = rop_f(vx, vv)
      v2 = scan_f(vx, vv)
  
      assert np.allclose(v1, v2), f"ROP mismatch: {v1} {v2}"
  
      self.check_nondiff_rop(
          pytensor.clone_replace(
              y, replace={self.mx: break_op(self.mx)}
          )
      )
  
      vv = np.asarray(
          self.rng.uniform(size=out_shape), pytensor.config.floatX
      )
      yv = Lop(y, self.mx, self.v)
      lop_f = function([self.mx, self.v], yv)
  
      sy = grad((self.v * y).sum(), self.mx)
      scan_f = function([self.mx, self.v], sy)
  
      v1 = lop_f(vx, vv)
      v2 = scan_f(vx, vv)
      assert np.allclose(v1, v2), f"LOP mismatch: {v1} {v2}"
  
imports: import numpy
  import pytest
  import pytensor
  import pytensor.tensor
  from pytensor import function
  from pytensor.gradient import Lop, Rop, grad, grad_undefined
  from pytensor.graph.basic import Apply
  from pytensor.graph.op import Op
  from pytensor.tensor.math import argmax, dot
  from pytensor.tensor.math import max
  from pytensor.tensor.shape import unbroadcast
  from pytensor.tensor.type import matrix, vector
  from tests import unittest_tools
label_desc: Use image node_id 3 for calling the RopLopChecker obj's underlying member method code with example usage: obj.check_mat_rop_lop(y, out_shape) without return types