code: def test_tensor_ring_als(
      tensor_shape,
      rank,
      ls_solve,
      random_state,
      er_decrease_tol,
      monkeypatch,
  ):
      rng = tl.check_random_state(random_state)
  
      # Generate random tensor which has exact tensor ring decomposition
      tensor = random_tr(
          tensor_shape,
          rank,
          full=True,
          random_state=rng,
          dtype=tl.float64,
      )
  
      # Ensure ValueError is raised for when invalid ls_solve is given
      with np.testing.assert_raises(ValueError):
          tr_decomp = tensor_ring_als(
              tensor,
              rank,
              random_state=rng,
              ls_solve="invalid_ls_solve",
          )
  
      # Create callback function for error tracking and run decomposition
      callback = ErrorTracker()
      tr_decomp = tensor_ring_als(
          tensor,
          rank,
          random_state=rng,
          callback=callback,
          ls_solve=ls_solve,
      )
  
      # Ensure decomposition returns right number of factors
      assert_(len(tr_decomp.factors) == len(tensor_shape))
  
      # Ensure cores are sized correctly
      for i in range(len(tensor_shape)):
          core_shape = tr_decomp[i].shape
          assert_(core_shape[0] == rank[i])
          assert_(core_shape[1] == tensor_shape[i])
          assert_(core_shape[2] == rank[i + 1])
  
      # Compute decomposition relative error and ensure it's small enough
      rel_error_tol = 1e-2
      rel_error = tl.norm(
          tl.tr_to_tensor(tr_decomp) - tensor
      ) / tl.norm(tensor)
      assert_(rel_error < rel_error_tol)
  
      # Ensure error decreases monotonically (up to numerical error)
      for i in range(len(callback.error) - 1):
          assert_(
              callback.error[i + 1]
              < callback.error[i] + er_decrease_tol
          )
  
      # Ensure TensorRingALS class passes arguments correctly to decomposition function
      assert_class_wrapper_correctly_passes_arguments(
          monkeypatch, tensor_ring_als, TensorRingALS, rank=3
      )
  
      # Ensure that the computed decomposition is the same when the same random seed is
      # used
      rng1 = tl.check_random_state(random_state)
      rng2 = tl.check_random_state(random_state)
      callback1 = ErrorTracker()
      callback2 = ErrorTracker()
      tr_decomp1 = tensor_ring_als(
          tensor,
          rank,
          random_state=rng1,
          callback=callback1,
          ls_solve=ls_solve,
      )
      tr_decomp2 = tensor_ring_als(
          tensor,
          rank,
          random_state=rng2,
          callback=callback2,
          ls_solve=ls_solve,
      )
      assert_array_almost_equal(callback1.error, callback2.error)
      for i in range(len(tr_decomp1.factors)):
          assert_array_almost_equal(tr_decomp1[i], tr_decomp2[i])
  
file_path: tensorly/tensorly/decomposition/tests/test_tr_decomposition.py
imports: import pytest
  import tensorly
  import numpy
  from .._tr import tensor_ring, tensor_ring_als, TensorRingALS
  from ...random import random_tr
  from ...testing import assert_, assert_array_almost_equal, assert_raises, assert_class_wrapper_correctly_passes_arguments
label_desc: Use image node_id 3 for calling a global function with example usage: test_tensor_ring_als(tensor_shape, rank, ls_solve, random_state, er_decrease_tol, monkeypatch) without return types