class ApplySymbolVariable(GeneralizedVariable):
  def __init__(self, variable, symbol):
    self.variable = variable
    self.symbol = symbol
  def __eq__(self, other):
    return (other.__class__ == ApplySymbolVariable
        and self.variable == other.variable
        and self.symbol == other.symbol)
  def applied_variables(self):
    if isinstance(self.symbol, Variable):
      return Set([self.symbol]).union(self.variable.applied_variables())
    else:
      return self.variable.applied_variables()
  def __ne__(self, other):
    return not (self == other)
  def __repr__(self):
    return "<: " + repr(self.variable) + " :: " + repr(self.symbol) + " :>"
  def updateVariables(self):
    return ApplySymbolVariable(variable = self.variable.updateVariables(), symbol = self.symbol)
  def substituteVariable(self, a, b):
    return ApplySymbolVariable(variable = self.variable.substituteVariable(a, b), symbol = self.symbol)
  def freeVariables(self):
    return self.variable.freeVariables()

  def render(self):
    symbolBackgroundColor, variableBackgroundColor = colors_for_symbol(self.symbol)
    if isinstance(self.symbol, Variable):
      if self.symbol.infix is not None:
        return primitives.wrapVariableInfix(renderInfix(self.variable, self.symbol.infix, self.symbol))
      else:
        symbolStack = self.symbol.render()
        return self.variable.render().stack(0, primitives.dot).stack(0, symbolStack)
    else:
      symbolStack = renderSymbol(self.symbol)
      return self.variable.render().stack(0, primitives.dot).stack(0, symbolStack) class ProductVariable(GeneralizedVariable):
  def __init__(self, symbol_variable_pairs):
    self.symbol_variable_pairs = symbol_variable_pairs

  def applied_variables(self):
    result = Set([])
    for symbol, variable in self.symbol_variable_pairs:
      result.union_update(variable.applied_variables())
    return result

  def __eq__(self, other):
    return (other.__class__ == ProductVariable
        and self.symbol_variable_pairs == other.symbol_variable_pairs)
  def __ne__(self, other):
    return not(self == other)
  def __repr__(self):
    return "{" + ", ".join([repr(s) + ": " + repr(v) for (s,v) in self.symbol_variable_pairs]) + "}"
  def updateVariables(self):
    return ProductVariable(
        symbol_variable_pairs = [(s, v.updateVariables()) for (s,v) in self.symbol_variable_pairs])
  def substituteVariable(self, a, b):
    return ProductVariable(
        symbol_variable_pairs = [(s, v.substituteVariable(a, b))
                                 for (s,v) in self.symbol_variable_pairs])
  def freeVariables(self):
    result = Set()
    for (s, v) in self.symbol_variable_pairs:
      result.union_update(v.freeVariables())
    return result

  def render(self):
    symbolVariablePairs = []
    for i in range(len(self.symbol_variable_pairs)):
      (s,v) = self.symbol_variable_pairs[i]
      (c0, c1) = colors.productPairsColor(i)
      symbolVariablePairs.append(renderSymbolVariablePair(renderSymbol(s),
        v.render(), c0, c1))
    return stack.stackAll(0, symbolVariablePairs,
        spacing = distances.productVariableHorizontalSpacing) class StringVariable(Variable):
  # infix: either None, or a pair of symbols (a, b) such that when this variable holds
  #        of a variable v, v is a product variable over symbols a and b.
  def __init__(self, name, infix = None):
    self._generate_id()
    self._name = name
    self.infix = infix

  def relatedVariable(self):
    return StringVariable(name = self.name() + "'", infix = self.infix)

  def render(self):
    return primitives.newTextStack(colors.variableColor, repr(self))

  def name(self):
    return self._name

  def __repr__(self):
    return self.name()

  def updateVariables(self):
    return self.relatedVariable() 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]) class SearchSpec:
class SimpleSearchSpec(SearchSpec):
  def definitons_only(self):
  def valid(self, formula):
  def search_hidden_formula(self, name):
  def __init__(self, f):
  def valid(self, formula):
  def search_hidden_formula(self, name):
def equal_translates_search_spec(formula): class Formula:
class Arrow:
class Holds(Formula):
class Not(Formula):
class Exists(Formula):
class Always(Formula):
class WellDefined(Formula):
class Conjunction(Formula):
class And(Conjunction):
class Or(Conjunction):
class Iff(Formula):
class Hidden(Formula):
class Identical(Formula):
class Unique(Formula):
class RenderingContext:
  def translate(self):
  def _translate(self):
  def forwardGatherExistentials(self):
  def _forwardGatherExistentials(self):
  def search(self, spec):
  def forwardSimplify(self):
  def backwardSimplify(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def top_level_render(self, covariant = True):
  def render(self, context):
  def substituteVariable(self, a, b):
  def applied_variables(self):
  def updateVariables(self):
  def is_and(self):
  def compress(self):
  def backwardUndoubleDual(self):
  def forwardAndTrue(self):
  def identity(self):
  def __init__(self, src, tgt, basicArrow):
  def translate(self):
  def compress(self):
  def invert(self):
  def forwardCompose(self, arrow):
  def backwardCompose(self, arrow):
  def forwardFollow(self, f):
  def backwardFollow(self, f):
  def __init__(self, held, holding):
  def applied_variables(self):
  def __repr__(self):
  def _translate(self):
  def render(self, context):
  def substituteVariable(self, a, b):
  def updateVariables(self):
def _isUnit(x):
  def __init__(self, value):
  def applied_variables(self):
  def forwardSimplify(self):
  def backwardSimplify(self):
  def forwardUndoubleDual(self):
  def backwardDoubleDual(self):
  def __repr__(self):
  def _translate(self):
  def render(self, context):
  def substituteVariable(self, a, b):
  def updateVariables(self):
  def __init__(self, bindings, value):
  def _forwardGatherExistentials(self):
  def applied_variables(self):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def substituteAllVariablesInBody(self, variables):
  def forwardMaybeCollapse(self):
      def f(i, x):
  def forwardSimplify(self):
  def backwardSimplify(self):
  def __repr__(self):
  def _endofunctor_translate(self):
  def _translate(self):
  def forwardSplit(self, i):
  def forwardPushAndSplit(self, i):
  def forwardPush(self, i):
  def render(self, context):
  def __init__(self, value):
  def applied_variables(self):
  def search(self, spec):
  def forwardJoin(self):
  def forwardSimplify(self):
  def backwardCojoin(self):
  def backwardSimplify(self):
  def forwardUnalways(self):
  def __repr__(self):
  def _translate(self):
  def render(self, context):
  def substituteVariable(self, a, b):
  def updateVariables(self):
  def __init__(variable, newVariable, equivalence, value):
  def forwardSimplify(self):
  def backwardSimplify(self):
  def _translate(self):
  def getBasicFunctor(self):
  def render(self, context):
  def substituteVariable(self, a, b):
  def updateVariables(self):
def ExpandWellDefined(variable, newVariable, equivalence):
  def __init__(self, values):
  def __repr__(self):
  def _translate(self):
  def applied_variables(self):
  def forwardSimplify(self):
  def forwardSimplifyConjunction(self):
  def forwardMaybeUnsingleton(self):
  def backwardMaybeUnsingleton(self):
  def backwardSimplify(self):
  def backwardSimplifyConjunction(self):
  def myUnit(self, x):
  def forwardRemoveUnits(self):
          def f(i):
  def backwardIntroduceUnits(self):
  def forwardMoveBack(self, i, amount):
  def forwardMoveForward(self, i, amount):
    def f(j, x):
        def g(k, x):
  def forwardOnArrows(self, arrows):
    def f(i):
  def substituteVariable(self, a, b):
  def updateVariables(self):
  def render(self, context):
  def is_and(self):
  def search(self, spec):
  def forwardSubstituteIdentical(self, a, b):
  def _forwardGatherExistentials(self):
    def f(i):
  def liftBasicExistsBothSides(self):
  def forwardDistribute(self, i, j):
  def forwardDistributeToNext(self, i):
    def f(k, x):
        def g(k, x):
  def name(self):
  def basicBinop(self):
  def basicUnit(self):
  def renderDivider(self, covariant, length):
  def forwardTotalCollapse(self, index):
    def f(i, x):
  def forwardCommutePair(self):
  def forwardDistributePair(self):
  def forwardDistributePairOther(self):
  def backwardTotalCollapse(self, index):
  def basicBinop(self):
  def name(self):
  def renderDivider(self, covariant, length):
  def backwardAdmitRight(self):
  def backwardAdmitLeft(self):
  def basicUnit(self):
  def forwardTotalCollapse(self, index):
  def backwardTotalCollapse(self, index):
    def f(i, x):
  def __init__(self, left, right):
  def applied_variables(self):
  def __repr__(self):
  def _translate(self):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def forwardLeftToRight(self):
  def forwardRightToLeft(self):
  def render(self, context):
  def __init__(self, base, name):
  def applied_variables(self):
  def search(self, spec):
  def __repr__(self):
  def _translate(self):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def __init__(self, left, right):
  def forwardSimplify(self):
  def applied_variables(self):
  def __repr__(self):
  def _translate(self):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def render(self, context):
  def forwardSimplify(self):
  def backwardSimplify(self):
def InDomain(x, e):
def Equal(a, b, e):
  def __init__(self, variable, equivalence, formula, newVariable = None):
  def _translate(self):
  def substituteVariable(self, a, b):
  def updateVariables(self):
  def render(self, context):
  def __init__(self, covariant):
  def negate(self):
  def as_covariant(self):
def getInfix(holds):
def renderWithBackground(s, border_width, color):
def _dimension_for_variance(covariant):
    A = self.bindings[:i]
    D = self.bindings[i+2:]
  F = basicEndofunctor.SubstituteVariable(variable, newVariable).compose(
      basicEndofunctor.not_functor.compose(
        basicEndofunctor.And(side = right, other = isEqual)).compose(
          basicEndofunctor.Exists(newVariable)).compose(
            basicEndofunctor.not_functor))
    X = left_exists.value.translate()
    Y = right_exists.value.translate() class Formula:
class Holds(Formula):
class Exists(Formula):
class Conjunction(Formula):
class And(Conjunction):
class Or(Conjunction):
class Not(Formula):
class Always(Formula):
class Unit(Formula):
class AndUnit(Unit):
class OrUnit(Unit):
class Identical(Formula):
class Arrow:
class Isomorphism(Arrow):
class InverseArrow(Isomorphism):
class Id(Isomorphism):
class Composite(Arrow):
class Distribute(Arrow):
class Induction(Arrow):
class Forget(Arrow):
class Admit(Arrow):
class Commute(Isomorphism):
class Associate(Isomorphism):
class UnitIdentity(Isomorphism):
class DoubleDual(Isomorphism):
class Apply(Arrow):
class Cojoin(Arrow):
class Copy(Arrow):
class Zip(Arrow):
class Unalways(Arrow):
class IntroExists(Arrow):
class AndPastExists(Isomorphism):
class CommuteExists(Isomorphism):
class AlwaysPastExists(Isomorphism):
class RemoveExists(Arrow):
class NotTrueIsFalse(Isomorphism):
class NotFalseIsTrue(Isomorphism):
class SubstituteArrow(Arrow):
class TrueAlways(Isomorphism):
class IdenticalReflexive(Isomorphism):
class FunctorialArrow(Arrow):
class OnConjunction(FunctorialArrow):
class OnAlways(FunctorialArrow):
class OnBody(FunctorialArrow):
class OnNot(FunctorialArrow):
class Assumption:
class SingleAssumption:
class CombinedAssumption(Assumption):
class DependentArrow:
  def simplify(self):
  def produceFiltered(self, f):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def freeVariables(self):
  def forwardDoubleDual(self):
  def forwardAssume(self, a):
  def forwardAndTrue(self):
  def backwardUnalways(self):
  def forwardAdmitLeft(self, x):
  def forwardAdmitRight(self, x):
  def backwardForgetLeft(self, x):
  def backwardForgetRight(self, x):
  def forwardIntroExists(self, variable, oldVariable):
  def backwardRemoveExists(self, variable):
  def forwardHide(self, name):
  def forwardCollapse(self):
  def identity(self):
  def __init__(self, held, holding):
  def __eq__(self, other):
  def __ne__(self, other):
  def __repr__(self):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def freeVariables(self):
def isExistentialOfLength(n, existential):
  def __init__(self, variable, value):
  def simplify(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def __repr__(self):
  def produceFiltered(self, f):
  def forwardOnBody(self, arrow):
  def backwardOnBody(self, arrow):
  def forwardOnBodyFollow(self, f):
  def backwardOnBodyFollow(self, f):
  def forwardRemoveExists(self):
  def backwardIntroExists(self, newVariable):
  def forwardCommuteExists(self):
  def forwardExistsPastAnd(self):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def freeVariables(self):
def MultiExists(variables, value):
def MultiBoundedExists(variable_domain_pairs, value):
def MultiForall(variables, value):
def MultiBoundedForall(variable_domain_pairs, value):
  def __init__(self, left, right):
  def simplify(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def forwardOnConjunction(self, leftArrow, rightArrow):
  def backwardOnConjunction(self, leftArrow, rightArrow):
  def forwardOnLeft(self, arrow):
  def forwardOnRight(self, arrow):
  def backwardOnLeft(self, arrow):
  def backwardOnRight(self, arrow):
  def forwardOnLeftFollow(self, f):
  def forwardOnRightFollow(self, f):
  def backwardOnLeftFollow(self, f):
  def backwardOnRightFollow(self, f):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def freeVariables(self):
  def forwardCommute(self):
  def backwardCommute(self):
  def forwardAssociate(self):
  def backwardAssociate(self):
  def forwardAssociateOther(self):
  def backwardAssociateOther(self):
  def produceFiltered(self, f):
  def getSide(self, side):
  def getOtherSide(self, side):
  def simplifyOnce(self):
  def forwardRemoveRightIfUnit(self):
  def simplify(self):
  def backwardIntroUnitLeft(self):
  def forwardSubstituteIdentical(self, a, b):
  def forwardApply(self):
  def forwardContradict(self):
  def forwardZip(self):
  def forwardAndPastExists(self):
  def forwardAndPastExistsOther(self):
  def forwardDistibute(self):
    def pairWith(x):
  def forwardDistributeLeft(self):
  def forwardDistributeRight(self):
  def backwardCopy(self):
  def forwardForgetLeft(self):
  def forwardForgetRight(self):
  def __repr__(self):
  def __repr__(self):
  def simplifyOnce(self):
  def forwardRemoveRightIfUnit(self):
  def simplify(self):
  def backwardAdmitLeft(self):
  def backwardAdmitRight(self):
def multiple_conjunction(conjunction, values):
def MultiAnd(values):
def MultiOr(values):
def Implies(predicate, consequent):
def ExpandIff(left, right):
  def __init__(self, value, rendered = False):
  def simplify(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def __repr__(self):
  def forwardOnNot(self, arrow):
  def forwardOnNotFollow(self, f):
  def backwardOnNot(self, arrow):
  def backwardOnNotFollow(self, f):
  def backwardDoubleDual(self):
  def forwardUndoubleDual(self):
  def backwardApply(self, a):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def freeVariables(self):
  def __init__(self, value):
  def simplify(self):
  def produceFiltered(self, f):
  def forwardCopy(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def __repr__(self):
  def forwardUnalways(self):
  def forwardOnAlways(self, arrow):
  def backwardOnAlways(self, arrow):
  def forwardOnAlwaysFollow(self, f):
  def backwardOnAlwaysFollow(self, f):
  def forwardAlwaysPastExists(self):
  def forwardDistributeAlways(self):
  def forwardCojoin(self):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def freeVariables(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def freeVariables(self):
  def __repr__(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def __repr__(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def __init__(self, left, right):
  def __eq__(self, other):
  def __ne__(self, other):
  def updateVariables(self):
  def substituteVariable(self, a, b):
  def freeVariables(self):
  def __repr__(self):
def unit_for_conjunction(conjunction):
  def __init__(self, src, tgt):
  def substituteVariable(self, a, b):
  def leftAssociate(self):
  def _leftAssociate(self, f):
  def rightAssociate(self):
  def _rightAssociate(self, f):
  def compress(self):
  def __repr__(self):
  def validate(self):
  def invert(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def forwardCompose(self, other):
  def backwardCompose(self, other):
  def forwardFollow(self, f):
  def backwardFollow(self, f):
  def invert(self):
  def __init__(self, arrow):
  def substituteVariable(self, a, b):
  def __repr__(self):
  def invert(self):
  def arrowTitle(self):
  def validate(self):
  def compose(self, other):
def _compress2(left, right):
def _commutingArrow(arrow):
  def __init__(self, left, right):
  def substituteVariable(self, a, b):
  def compress(self):
  def _compress_rightAssocitaed(self):
  def _compress_rightAssociatedCompressed(self):
  def leftAssociate(self):
  def _leftAssociate(self, f):
  def rightAssociate(self):
  def _rightAssociate(self, f):
  def __repr__(self):
  def validate(self):
  def invert(self):
  def __eq__(self, other):
  def __ne__(self, other):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def invert(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def arrowTitle(self):
  def validate(self):
  def name(self):
  def validate(self):
  def __repr__(self):
  def substituteVariable(self, a, b):
  def compress(self):
  def reprAround(self, middle):
def OnAnd(leftArrow, rightArrow):
def OnOr(leftArrow, rightArrow):
  def __init__(self, leftArrow, rightArrow, src, tgt):
  def substituteVariable(self, a, b):
  def invert(self):
  def compress(self):
  def __repr__(self):
  def arrowTitle(self):
  def __init__(self, arrow):
  def invert(self):
  def arrowTitle(self):
  def __init__(self, variable, arrow):
  def invert(self):
  def compress(self):
  def arrowTitle(self):
  def __init__(self, arrow):
  def invert(self):
  def arrowTitle(self):
def _hconcat(left, right):
  def as_formula(self):
  def add_always(self):
  def import_assumption(self, endofunctor):
  def __init__(self, formula):
  def as_formula(self):
  def add_always(self):
  def import_assumption(self, endofunctor):
  def __init__(self, left, right):
  def as_formula(self):
  def add_always(self):
  def import_assumption(self, endofunctor):
def identity_dependent_arrow(formula):
  def __init__(self, src, tgt, assumption, arrow):
  def dependent_arrow_not(self):
  def always(self):
  def exists(self, variable):
  def compose(self, other):
  def dependent_arrow_and(self, other):
  def dependent_arrow_or(self, other):
    I = self.left
    A = self.src.right class UnliftableException(Exception):
class UnimportableException(Exception):
class Endofunctor:
class Exists(Endofunctor):
class Always(Endofunctor):
class Not(Endofunctor):
class Id(Endofunctor):
class Composite(Endofunctor):
class Conjunction(Endofunctor):
class And(Conjunction):
class Or(Conjunction):
class SubstituteVariable(Endofunctor):
  def __init__(self, functor, B):
  def __str__(self):
  def __init__(self, formula, endofunctor):
  def __str__(self):
  def variables(self):
  def importFiltered(self, f):
  def exportFiltered(self, f):
  def _import(self, B):
  def _importOther(self, B):
  def _export(self, B):
  def lift(self, B):
  def liftExists(self, variable):
  def _liftExists(self, variable):
  def onObject(self, object):
  def onArrow(self, arrow):
  def negations(self):
  def covariant(self):
  def pop(self):
  def compose(self, other):
  def importExactly(self, e):
    def f(x):
  def exportExactly(self, B):
    def f(x):
  def exportBottom(self, x):
  def contradictBottomCovariant(self, x):
  def exportLeft(self, x):
  def exportRight(self, x):
  def exportSide(self, side, x):
  def exportRecursively(self, instantiator, x):
  def exportNestedAnd(self, x, limit, f):
  def __init__(self, variable):
  def __repr__(self):
  def _import(self, B):
  def variables(self):
  def onObject(self, object):
  def onArrow(self, arrow):
  def negations(self):
  def lift(self, B):
  def __repr__(self):
  def _import(self, B):
  def _liftExists(self, variable):
  def variables(self):
  def onObject(self, object):
  def onArrow(self, arrow):
  def negations(self):
  def __repr__(self):
  def _export(self, b):
  def variables(self):
  def onObject(self, object):
  def onArrow(self, arrow):
  def negations(self):
  def __repr__(self):
  def _import(self, B):
  def lift(self, B):
  def variables(self):
  def pop(self):
  def onObject(self, object):
  def onArrow(self, arrow):
  def negations(self):
  def __init__(self, left, right):
  def __repr__(self):
  def covariant(self):
  def lift(self, B):
  def _liftExists(self, variable):
  def _import(self, B):
  def _export(self, B):
  def importFilteredCovariantCovariant(self, f):
  def importFilteredContravariantContravariant(self, f):
  def importFiltered(self, f):
  def exportFilteredContravariantCovariant(self, f):
  def exportFilteredCovariantContravariant(self, f):
  def exportFiltered(self, f):
  def variables(self):
  def pop(self):
  def onObject(self, object):
  def onArrow(self, arrow):
  def negations(self):
  def __init__(self, side, other):
  def __repr__(self):
  def variables(self):
  def createObject(self, left, right):
  def createArrow(self, leftArrow, rightArrow):
  def onObject(self, object):
  def onArrow(self, arrow):
  def negations(self):
  def createObject(self, left, right):
  def stringDivider(self):
  def lift(self, B):
  def _liftExists(self, variable):
  def _import(self, B):
  def importFiltered(self, f):
  def stringDivider(self):
  def _import(self, B):
  def createObject(self, left, right):
  def __init__(self, oldVariable, newVariable):
  def __repr__(self):
  def variables(self):
  def _import(self, B):
  def lift(self, B):
  def onObject(self, object):
  def onArrow(self, arrow):
  def negations(self):
def substitutionArrow(endofunctor, x, a, b):
def holdsSubstitutionArrow(endofunctor, holds, a, b):
      C = B.value class UntransportableException(Exception):
class UntransportingOrException(UntransportableException):
class Bifunctor:
class Commute(Bifunctor):
class And(Bifunctor):
class Or(Bifunctor):
class PostcompositeBifunctor(Bifunctor):
class PrecompositeBifunctor(Bifunctor):
class Join(endofunctor.Endofunctor):
  def __init__(self, unliftableException):
  def __str__(self):
  def __init__(self, B):
  def __str__(self):
  def onObjects(self, left, right):
  def onArrows(self, left, right):
  def _import(self, B):
  def variables(self):
  def _importLeft(self, B):
  def _importRight(self, B):
  def _liftLeft(self, B):
  def _liftRight(self, B):
  def transport_duplicating(self, B):
  def transport(self, B):
  def precompose(self, left, right):
  def precomposeLeft(self, left):
  def precomposeRight(self, right):
  def compose(self, other):
  def join(self):
  def commute(self):
  def __init__(self, bifunctor):
  def __repr__(self):
  def onObjects(self, left, right):
  def onArrows(self, left, right):
  def _import(self, B):
  def variables(self):
  def _importLeft(self, B):
  def _importRight(self, B):
  def _liftLeft(self, B):
  def _liftRight(self, B):
  def __repr__(self):
  def onObjects(self, left, right):
  def onArrows(self, left, right):
  def variables(self):
  def _import(self, B):
  def _liftLeft(self, B):
  def _liftRight(self, B):
  def _importLeft(self, B):
  def _importRight(self, B):
  def __repr__(self):
  def onObjects(self, left, right):
  def onArrows(self, left, right):
  def variables(self):
  def _import(self, B):
  def _importLeft(self, B):
  def _importRight(self, B):
  def __init__(self, bifunctor, functor):
  def __repr__(self):
  def variables(self):
  def _liftLeft(self, B):
  def _liftRight(self, B):
  def onArrows(self, left, right):
  def onObjects(self, left, right):
  def precompose(self, left, right):
  def compose(self, other):
  def _import(self, B):
  def _importLeft(self, B):
  def _importRight(self, B):
  def __init__(self, bifunctor, left, right):
  def __repr__(self):
  def variables(self):
  def _liftLeft(self, B):
  def _liftRight(self, B):
  def onArrows(self, left, right):
  def onObjects(self, left, right):
  def precompose(self, left, right):
  def _importRight(self, B):
  def _importLeft(self, B):
  def _import(self, B):
  def __init__(self, bifunctor):
  def __repr__(self):
  def importFiltered(self, f):
  def _import(self, B):
  def lift(self, B):
  def variables(self):
  def lift(self, B):
  def onObject(self, object):
  def onArrow(self, arrow):
  def covariant(self): class FinishedInstantiatingException(Exception):
class Instantiator:
  def instantiate(self, variable, endofunctor, formula):
  def exportSide(self, formula, endofunctor): A = lambda: StringVariable('A')
B = lambda: StringVariable('B')
C = lambda: StringVariable('C')
R = lambda: StringVariable('R')
S = variable.StringVariable('S') def newTextStack(color, s):
def wrapVariableInfix(s):
def holds():
def surroundWithNot(s):
def solidSquare(color, widths):
def identical(covariant):
def iff():
def _dimension_for_variance(covariant):
def _dual_dimension(dimension):
def andDivider(covariant):
  def f(length):
def orDivider(covariant):
  def f(length):
def quantifierDivider(covariant, length):
def divider(color, dimension, length, width, special_character = None): def productPairsColor(i):
def exponentialColor(isAlways): def stack(self, dimension, other, spacing = 0):
  if self._backend.stacks():
    offset = [0 for i in range(self.dimension())]
    offset[dimension] = spacing
    coords = list(self._coords)
    for i in range(len(coords)):
      if i == dimension:
        coords[i] += spacing + other._coords[i]
      else:
        coords[i] = max(coords[i], other._coords[i])
    return Stack(coords, self._backend.stack(dimension, other._backend.shift(offset)))
  else:
    offset = [0 for i in range(self.dimension())]
    offset[dimension] = self.widths()[dimension] + spacing
    return self.below(other.shift(offset))
from misc import *
from calculus.variable import ApplySymbolVariable, ProductVariable, StringVariable, Variable
from calculus.enriched import spec, formula as formula
from calculus.basic import formula as basicFormula
from calculus.basic import endofunctor as basicEndofunctor
from calculus.basic import bifunctor as basicBifunctor
from calculus.basic import instantiator
from lib import common_symbols, common_vars
from lib.common_symbols import leftSymbol, rightSymbol, relationSymbol, domainSymbol
from ui.render.text import primitives, colors, distances
from ui.stack import stack
import misc

  def is_and_functor(self):
    return False

  def updateVariables(self):
    raise Exception("Abstract superclass.")

  # spec: a SearchSpec instance.
  # return: if self.covariant(): a list of claims importable at self matching spec
  #         otherwise:  a list of claims exportable at self matching spec
  def search(self, spec):
    raise Exception("Abstract superclass.")

  # self must not be the identity functor.
  # return a pair of endofunctors (a, b) such that a.compose(b) == self, a is non-trivial
  # and a is "as small as possible".
  def factor_left(self):
    return (self, identity_functor)

  # self must not be the identity functor.
  # return a pair of endofunctors (a, b) such that a.compose(b) == self, b is non-trivial
  # and b is "as small as possible".
  def factor_right(self):
    return (identity_functor, self)

  def onArrow(self, arrow):
    if self.is_identity():
      return arrow
    else:
      basicArrow = self.translate().onArrow(arrow.translate())
      if self.covariant():
        src = self.onObject(arrow.src)
        tgt = self.onObject(arrow.tgt)
      else:
        src = self.onObject(arrow.tgt)
        tgt = self.onObject(arrow.src)
      return formula.Arrow(src = src, tgt = tgt, basicArrow = basicArrow)

  def compose(self, other):
    return Composite(self, other)

  def is_identity(self):
    return is_identity_functor(self)

  # self must be contravariant
  # formula: an Exists formula.
  # variables: a list of variable in scope in self.
  # return: a pair (arrow, value) such that arrow.tgt == self.onObject(value) and arrow instantiates the exists formula
  #         with the given variables.
  def instantiateInOrder(self, variables, x):
    assert(not self.covariant())
    assert(x.__class__ == formula.Exists)
    assert(len(variables) == len(x.bindings))
    value = fully_substituted(variables, x)
    ins = InOrderInstantiator(variables)
    basicArrow = self.translate().exportRecursively(ins, x.translate())
    if not ins.complete():
      raise Exception("Instantiation did not complete.")
    result = formula.Arrow(src = self.onObject(x),
        tgt = self.onObject(value),
        basicArrow = basicArrow)
    return result, value

  def exportAutomaticallFromAnd(self, x):
    assert(not self.covariant())
    def try_export(y):
      if y.__class__ == basicFormula.Always:
        return y.value.__class__ == basicFormula.Holds
      else:
        return y.__class__ == basicFormula.Holds
    xs, basicArrow = self.translate().exportNestedAnd(x.translate(), len(x.values), try_export)
    newValues = []
    for i in range(len(x.values)):
      if xs[i] == False:
        newValues.append(x.values[i])
    newX = formula.And(newValues)
    result = formula.Arrow(src = self.onObject(x), tgt = self.onObject(newX),
        basicArrow = basicArrow)
    return result, newX

  def importExactly(self, B):
    assert(self.covariant())
    return (lambda x:
        formula.Arrow(src = self.onObject(x),
          tgt = self.onObject(formula.And([B, x])),
          basicArrow = self.translate().importExactly(B.translate())(x.translate())))

  def importAboutGenerally(self, f, g, x):
    class S(spec.SearchSpec):
      def search_hidden_formula(self, name):
        return True
      def valid(self, e):
        return e.__class__ == formula.Always and f([], e.value)
    importable_claims = self.search(S())
    claim = importable_claims[g(importable_claims)]
    import_arrow = self.importExactly(claim)(x)
    return import_arrow, formula.And([claim, x])

  # self must be covariant
  # variables: a list of variable in scope at self.
  # f: a function from a list of variables bindings and a formula to a boolean.
  # g: a function from a list of formulas to an index into that list.
  # x: a formula
  #
  # search this endofunctor for claims at covariant spots of the form:
  #  Forall(xs, Y) such that len(xs) == len(variables) and f(xs, Y) == True
  # pass the list L of substituted formulas to g to get an index I, and return a pair
  # (arrow, value) such that arrow imports and instantiates to get L[I]
  # and self.onObject(value) == arrow.tgt
  #   self -> L[i]
  def importAbout(self, variables, f, g, x):
    if len(variables) == 0:
      return self.importAboutGenerally(f, g, x)
    assert(self.covariant())
    # TODO Improve performance once it becomes important.
    class S(spec.SearchSpec):
      def search_hidden_formula(self, name):
        return True
      def valid(self, e):
        result = (e.__class__ == formula.Always

            and e.value.__class__ == formula.Not