code: def eliminate_implications(s):
      
      if not s.args or is_symbol(s.op): return s     ## (Atoms are unchanged.)
      args = map(eliminate_implications, s.args)
      a, b = args[0], args[-1]
      if s.op == '>>':
          return (b | ~a)
      elif s.op == '<<':
          return (a | ~b)
      elif s.op == '<=>':
          return (a | ~b) & (b | ~a)
      elif s.op == '^':
          assert len(args) == 2   ## TODO: relax this restriction
          return (a & ~b) | (~a & b)
      else:
          assert s.op in ('&', '|', '~')
          return Expr(s.op, *args)
docs: Change >>, <<, and <=> into &, |, and ~. That is, return an Expr
      that is equivalent to s, but has only &, |, and ~ as logical operators.
      >>> eliminate_implications(A >> (~B << C))
      ((~B | ~C) | ~A)
      >>> eliminate_implications(A ^ B)
      ((A & ~B) | (~A & B))