code: def test_truncation_discrete_logcdf(op_type, lower, upper):
      p = 0.7
      op = icdf_geometric if op_type == "icdf" else rejection_geometric
  
      x = op(p, name="x")
      xt = Truncated.dist(x, lower=lower, upper=upper)
      assert isinstance(xt.owner.op, TruncatedRV)
  
      xt_vv = xt.clone()
      xt_logcdf_fn = pytensor.function([xt_vv], logcdf(xt, xt_vv))
  
      ref_xt = scipy.stats.geom(p)
      log_norm = np.log(ref_xt.cdf(upper) - ref_xt.cdf(lower - 1))
  
      def ref_xt_logcdf(value):
          if value < lower:
              return -np.inf
          elif value > upper:
              return 0.0
  
          return (
              np.log(ref_xt.cdf(value) - ref_xt.cdf(lower - 1))
              - log_norm
          )
  
      for bound in (lower, upper):
          if np.isinf(bound):
              continue
          for offset in (-1, 0, 1):
              test_xt_v = bound + offset
              assert np.isclose(
                  xt_logcdf_fn(test_xt_v), ref_xt_logcdf(test_xt_v)
              )
  
imports: import numpy
  import pytensor
  import pytensor.tensor
  import pytest
  import scipy
  from pytensor.tensor.random.basic import GeometricRV, NormalRV
  from pymc import Censored, Model, draw, find_MAP
  from pymc.distributions.continuous import Exponential, Gamma, TruncatedNormal, TruncatedNormalRV
  from pymc.distributions.shape_utils import change_dist_size
  from pymc.distributions.transforms import _default_transform
  from pymc.distributions.truncated import Truncated, TruncatedRV, _truncated
  from pymc.exceptions import TruncationError
  from pymc.logprob.abstract import _icdf
  from pymc.logprob.basic import logcdf, logp
  from pymc.logprob.transforms import IntervalTransform
  from pymc.logprob.utils import ParameterValueError
  from pymc.testing import assert_moment_is_expected
label_desc: Use image node_id 9 for calling a global function with example usage: test_truncation_discrete_logcdf(op_type, lower, upper) and returns: unknown, unknown, int