code: def test_inducing_points_with_variable_shape() -> None:
      N, M1, D, P = 50, 13, 3, 1
      X, Y = np.random.randn(N, D), np.random.randn(N, P)
  
      Z1 = np.random.randn(M1, D)
  
      # use explicit tf.Variable with None shape:
      iv = giv.InducingPoints(
          tf.Variable(
              Z1,
              trainable=False,
              dtype=gpflow.default_float(),
              shape=(None, D),
          )
      )
      # Note that we cannot have Z be trainable if we want to be able to change its shape;
      # TensorFlow optimizers expect shape to be known at construction time.
  
      m = gpflow.models.SGPR(
          data=(X, Y),
          kernel=gpflow.kernels.Matern32(),
          inducing_variable=iv,
      )
  
      # Check 1: that we can still optimize with None shape
      opt = tf.optimizers.Adam()
  
      @tf.function
      def optimization_step() -> None:
          opt.minimize(m.training_loss, m.trainable_variables)
  
      optimization_step()
  
      # Check 2: that we can successfully assign a new Z with different number of inducing points!
      Z2 = np.random.randn(M1 + 1, D)
      m.inducing_variable.Z.assign(Z2)
  
      # Check 3: that we can also optimize with changed Z tensor
      optimization_step()
  
file_path: GPflow/tests/gpflow/test_inducing_variables.py
imports: from dataclasses import dataclass
  from typing import Callable, Optional, Tuple
  import numpy
  import pytest
  import tensorflow
  from check_shapes import get_shape
  from check_shapes.error_contexts import ErrorContext, MessageBuilder
  import gpflow
  import gpflow.inducing_variables
label_desc: Use image node_id 1 for calling a global function with example usage: test_inducing_points_with_variable_shape() without return types