def can_transpose_pass(self):
        """
         Return True if the one of the following is true:
         - (scenario 1) both inputs are of type _LazyTransposeHypotheticalValue, with the same perm value
         - one input is of type _LazyTransposeHypotheticalValue and the other satisfies one of the following:
             - (scenario 2) it is constant. In this case, the constant can be updated accordingly to allow the transpose to pass through
             - (scenario 3) if its non constant, then all of the following must be true
                 - its shape is fully defined
                 - the transpose compliment operation on the other input can be expressed via a reshape. This can
                   be done if there is only 1 non unit dimension in its shape, or if there are more than 1 non unit dims,
                   the transpose compliment operation only permutes the unit dimensions.

        In scenario 3, the transpose will be removed, by adding an extra static reshape.
        This is based on the assumption that a static reshape op will be less expensive than transpose.
        An example of scenario 3 is displayed below:

         Input pattern:

         (shape=(10, 20, 30))
              |
              |
              V
          Transpose op
          (shape = (20, 30, 10))
              |
              |
              V
          this op  <--------- (shape = (10,)) (other non const input)
              |
              V


         After transpose passes through:

         (shape=(10, 20, 30))
              |
              |
              V
          this op  <--------- (shape = (10, 1, 1)) Reshape op <---------- (shape = (10,)) (other non const input)
              |
              V
          Transpose op
          (shape = (20, 30, 10))
              |
              V

        """

        # ---------------------
        # check for scenario 1
        # --------------------
        # are both inputs _LazyTransposeHypotheticalValue?
        if self.other_input is None:
            return True

        # ---------------------
        # check for scenario 2
        # --------------------
        # is the second input a constant?
        rank = len(self.tranpose_input.shape)
        if len(self.transpose_axes) != rank:
            return False
        other_input_shape = self.other_input.shape
        if any_symbolic(other_input_shape):
            return False
        if len(other_input_shape) > rank:
            return False
        if isinstance(self.other_input.val, (np.ndarray, np.generic)):
            return True

        # ---------------------
        # check for scenario 3
        # --------------------
        # can other input be "reshaped" to allow the transpose to pass through?
        if any_symbolic(self.other_input.shape):
            return False
        transpose_compliment_perm = self._find_transpose_compliment(self.transpose_axes)
        # make the rank of the other input, same as that of the transpose input,
        # by broadcasting
        if len(other_input_shape) < rank:
            other_input_shape = [1] * (rank - len(other_input_shape)) + list(other_input_shape)

        # how many non unit dimensions in the other input's shape?
        if other_input_shape.count(1) in [rank, rank - 1]:
            # 0 or 1 non unit dimension
            return True
        else:
            # more than 1 non unit dimensions in other input
            # check if transpose is moving only dimensions that have values 1
            # if true, then the transpose compliment can be expressed via a reshape
            for i, axis in enumerate(transpose_compliment_perm):
                if i != axis and other_input_shape[axis] != 1:
                    return False
            return True

         Return True if the one of the following is true:
         - (scenario 1) both inputs are of type _LazyTransposeHypotheticalValue, with the same perm value
         - one input is of type _LazyTransposeHypotheticalValue and the other satisfies one of the following:
             - (scenario 2) it is constant. In this case, the constant can be updated accordingly to allow the transpose to pass through
             - (scenario 3) if its non constant, then all of the following must be true
                 - its shape is fully defined
                 - the transpose compliment operation on the other input can be expressed via a reshape. This can
                   be done if there is only 1 non unit dimension in its shape, or if there are more than 1 non unit dims,
                   the transpose compliment operation only permutes the unit dimensions.

        In scenario 3, the transpose will be removed, by adding an extra static reshape.
        This is based on the assumption that a static reshape op will be less expensive than transpose.
        An example of scenario 3 is displayed below:

         Input pattern:

         (shape=(10, 20, 30))
              |
              |
              V
          Transpose op
          (shape = (20, 30, 10))
              |
              |
              V
          this op  <--------- (shape = (10,)) (other non const input)
              |
              V


         After transpose passes through:

         (shape=(10, 20, 30))
              |
              |
              V
          this op  <--------- (shape = (10, 1, 1)) Reshape op <---------- (shape = (10,)) (other non const input)
              |
              V
          Transpose op
          (shape = (20, 30, 10))
              |
              V

        
coremltools/converters/mil/mil/passes/defs/optimize_repeat_ops.py