# Path: misc.py
# def flipSide(side):
# def _interleave(a, xs):
# 
# Path: calculus/symbol.py
# class Symbol:
# class StringSymbol(Symbol):
#   def __init__(self, type):
#   def _generate_id(self):
#   def __eq__(self, other):
#   def __ne__(self):
#   def __hash__(self):
#   def __repr__(self):
#   def __init__(self, s, type, infix = None):
#   def __repr__(self):
# 
# Path: calculus/variable.py
# class Variable(GeneralizedVariable):
#   def __init__(self):
#     self._generate_id()
# 
#   def _generate_id(self):
#     global n_variables
#     self._id = n_variables
#     n_variables += 1
# 
#   def updateVariables(self):
#     return Variable()
# 
#   def __eq__(self, other):
#     return self.__class__ == other.__class__ and self._id == other._id
#   def __ne__(self, other):
#     return not(self == other)
#   def __hash__(self):
#     return hash(self._id)
# 
#   def applied_variables(self):
#     return Set([])
# 
#   def __repr__(self):
#     return "<abstract variable %s>"%(self._id,)
# 
#   def substituteVariable(self, a, b):
#     if self == a:
#       return b
#     else:
#       return self
# 
#   def freeVariables(self):
#     return Set([self])
# 
# Path: lib/common_symbols.py



from misc import left, right
from calculus import symbol
from calculus.variable import Variable
from lib import common_symbols
from sets import Set
      and left.src.__class__ == right.src.__class__):
    return OnConjunction(src = left.src, tgt = right.tgt,
        leftArrow = left.leftArrow.forwardCompose(right.leftArrow),
        rightArrow = left.rightArrow.forwardCompose(right.rightArrow)).compress()
  elif left.__class__ == Id:
    return right
  elif right.__class__ == Id:
    return left
  elif _commutingArrow(left) and _commutingArrow(right):
    return left.src.identity()
  else:
    # TODO Improve compression.
    # There are many special cases of compressions.
    # For example: compress copy arrows with forget arrows.
    return Composite(left, right)

def _commutingArrow(arrow):
  return (arrow.__class__ == Commute or
    (arrow.__class__ == InverseArrow and arrow.arrow.__class__ == Commute))

# A --> B --> C
class Composite(Arrow):
  def __init__(self, left, right):
    self.left = left
    self.right = right
    self.src = left.src
    self.tgt = right.tgt
    self.validate()

  def substituteVariable(self, a, b):

# Path: misc.py
# def flipSide(side):
# def _interleave(a, xs):
# 
# Path: calculus/symbol.py
# class Symbol:
# class StringSymbol(Symbol):
#   def __init__(self, type):
#   def _generate_id(self):
#   def __eq__(self, other):
#   def __ne__(self):
#   def __hash__(self):
#   def __repr__(self):
#   def __init__(self, s, type, infix = None):
#   def __repr__(self):
# 
# Path: calculus/variable.py
# class Variable(GeneralizedVariable):
#   def __init__(self):
#     self._generate_id()
# 
#   def _generate_id(self):
#     global n_variables
#     self._id = n_variables
#     n_variables += 1
# 
#   def updateVariables(self):
#     return Variable()
# 
#   def __eq__(self, other):
#     return self.__class__ == other.__class__ and self._id == other._id
#   def __ne__(self, other):
#     return not(self == other)
#   def __hash__(self):
#     return hash(self._id)
# 
#   def applied_variables(self):
#     return Set([])
# 
#   def __repr__(self):
#     return "<abstract variable %s>"%(self._id,)
# 
#   def substituteVariable(self, a, b):
#     if self == a:
#       return b
#     else:
#       return self
# 
#   def freeVariables(self):
#     return Set([self])
# 
# Path: lib/common_symbols.py



# Path: calculus/basic/formula.py
from misc import left, right
from calculus import symbol
from calculus.variable import Variable
from lib import common_symbols
from sets import Set

      and left.src.__class__ == right.src.__class__):
    return OnConjunction(src = left.src, tgt = right.tgt,
        leftArrow = left.leftArrow.forwardCompose(right.leftArrow),
        rightArrow = left.rightArrow.forwardCompose(right.rightArrow)).compress()
  elif left.__class__ == Id:
    return right
  elif right.__class__ == Id:
    return left
  elif _commutingArrow(left) and _commutingArrow(right):
    return left.src.identity()
  else:
    # TODO Improve compression.
    # There are many special cases of compressions.
    # For example: compress copy arrows with forget arrows.
    return Composite(left, right)

def _commutingArrow(arrow):
  return (arrow.__class__ == Commute or
    (arrow.__class__ == InverseArrow and arrow.arrow.__class__ == Commute))

# A --> B --> C
class Composite(Arrow):
  def __init__(self, left, right):
    self.left = left
    self.right = right
    self.src = left.src
    self.tgt = right.tgt
    self.validate()

  def substituteVariable(self, a, b):

    return Composite(left = self.left.substituteVariable(a, b),