def couple(expr, jcoupling_list=None):
 a = expr.atoms(TensorProduct)
 for tp in a:
  if (not all([isinstance(state, SpinState) for state in tp.args])):
   continue
  if (not all([(state.__class__ is tp.args[0].__class__) for state in tp.args])):
   raise TypeError('All states must be the same basis')
  expr = expr.subs(tp, _couple(tp, jcoupling_list))
 return expr

def couple ( expr , jcoupling_list = None ) : a = expr . atoms ( TensorProduct ) for tp in a : if ( not all ( [ isinstance ( state , SpinState ) for state in tp . args ] ) ) : continue if ( not all ( [ ( state . __class__ is tp . args [ 0 ] . __class__ ) for state in tp . args ] ) ) : raise TypeError ( 'All states must be the same basis' ) expr = expr . subs ( tp , _couple ( tp , jcoupling_list ) ) return expr
couple a tensor product of spin states this function can be used to couple an uncoupled tensor product of spin states .