@register_canonicalize
@register_specialize
@gof.local_optimizer([T.Elemwise])
def local_func_inv(node):
 inv_pairs = ((basic.Deg2Rad, basic.Rad2Deg), (basic.Cosh, basic.ArcCosh), (basic.Tanh, basic.ArcTanh), (basic.Sinh, basic.ArcSinh), (basic.Conj, basic.Conj), (basic.Neg, basic.Neg), (basic.Inv, basic.Inv))
 x = node.inputs[0]
 if (not isinstance(node.op, T.Elemwise)):
  return
 if ((not x.owner) or (not isinstance(x.owner.op, T.Elemwise))):
  return
 prev_op = x.owner.op.scalar_op
 node_op = node.op.scalar_op
 for inv_pair in inv_pairs:
  if is_inverse_pair(node_op, prev_op, inv_pair):
   return x.owner.inputs
 return

@ register_canonicalize @ register_specialize @ gof . local_optimizer ( [ T . Elemwise ] ) def local_func_inv ( node ) : inv_pairs = ( ( basic . Deg2Rad , basic . Rad2Deg ) , ( basic . Cosh , basic . ArcCosh ) , ( basic . Tanh , basic . ArcTanh ) , ( basic . Sinh , basic . ArcSinh ) , ( basic . Conj , basic . Conj ) , ( basic . Neg , basic . Neg ) , ( basic . Inv , basic . Inv ) ) x = node . inputs [ 0 ] if ( not isinstance ( node . op , T . Elemwise ) ) : return if ( ( not x . owner ) or ( not isinstance ( x . owner . op , T . Elemwise ) ) ) : return prev_op = x . owner . op . scalar_op node_op = node . op . scalar_op for inv_pair in inv_pairs : if is_inverse_pair ( node_op , prev_op , inv_pair ) : return x . owner . inputs return
check for two consecutive operations that are functional inverses and remove them from the function graph .