class_docstr: Given a :class:`~.Diagram` and the corresponding
  :class:`DiagramGrid`, produces the Xy-pic representation of the
  diagram.
  
  The most important method in this class is ``draw``.  Consider the
  following triangle diagram:
  
  >>> from sympy.categories import Object, NamedMorphism, Diagram
  >>> from sympy.categories import DiagramGrid, XypicDiagramDrawer
  >>> A = Object("A")
  >>> B = Object("B")
  >>> C = Object("C")
  >>> f = NamedMorphism(A, B, "f")
  >>> g = NamedMorphism(B, C, "g")
  >>> diagram = Diagram([f, g], {g * f: "unique"})
  
  To draw this diagram, its objects need to be laid out with a
  :class:`DiagramGrid`::
  
  >>> grid = DiagramGrid(diagram)
  
  Finally, the drawing:
  
  >>> drawer = XypicDiagramDrawer()
  >>> print(drawer.draw(diagram, grid))
  \xymatrix{
  A \ar[d]_{g\circ f} \ar[r]^{f} & B \ar[ld]^{g} \\
  C &
  }
  
  For further details see the docstring of this method.
  
  To control the appearance of the arrows, formatters are used.  The
  dictionary ``arrow_formatters`` maps morphisms to formatter
  functions.  A formatter is accepts an
  :class:`ArrowStringDescription` and is allowed to modify any of
  the arrow properties exposed thereby.  For example, to have all
  morphisms with the property ``unique`` appear as dashed arrows,
  and to have their names prepended with `\exists !`, the following
  should be done:
  
  >>> def formatter(astr):
  ...   astr.label = r"\exists !" + astr.label
  ...   astr.arrow_style = "{-->}"
  >>> drawer.arrow_formatters["unique"] = formatter
  >>> print(drawer.draw(diagram, grid))
  \xymatrix{
  A \ar@{-->}[d]_{\exists !g\circ f} \ar[r]^{f} & B \ar[ld]^{g} \\
  C &
  }
  
  To modify the appearance of all arrows in the diagram, set
  ``default_arrow_formatter``.  For example, to place all morphism
  labels a little bit farther from the arrow head so that they look
  more centred, do as follows:
  
  >>> def default_formatter(astr):
  ...   astr.label_displacement = "(0.45)"
  >>> drawer.default_arrow_formatter = default_formatter
  >>> print(drawer.draw(diagram, grid))
  \xymatrix{
  A \ar@{-->}[d]_(0.45){\exists !g\circ f} \ar[r]^(0.45){f} & B \ar[ld]^(0.45){g} \\
  C &
  }
  
  In some diagrams some morphisms are drawn as curved arrows.
  Consider the following diagram:
  
  >>> D = Object("D")
  >>> E = Object("E")
  >>> h = NamedMorphism(D, A, "h")
  >>> k = NamedMorphism(D, B, "k")
  >>> diagram = Diagram([f, g, h, k])
  >>> grid = DiagramGrid(diagram)
  >>> drawer = XypicDiagramDrawer()
  >>> print(drawer.draw(diagram, grid))
  \xymatrix{
  A \ar[r]_{f} & B \ar[d]^{g} & D \ar[l]^{k} \ar@/_3mm/[ll]_{h} \\
  & C &
  }
  
  To control how far the morphisms are curved by default, one can
  use the ``unit`` and ``default_curving_amount`` attributes:
  
  >>> drawer.unit = "cm"
  >>> drawer.default_curving_amount = 1
  >>> print(drawer.draw(diagram, grid))
  \xymatrix{
  A \ar[r]_{f} & B \ar[d]^{g} & D \ar[l]^{k} \ar@/_1cm/[ll]_{h} \\
  & C &
  }
  
  In some diagrams, there are multiple curved morphisms between the
  same two objects.  To control by how much the curving changes
  between two such successive morphisms, use
  ``default_curving_step``:
  
  >>> drawer.default_curving_step = 1
  >>> h1 = NamedMorphism(A, D, "h1")
  >>> diagram = Diagram([f, g, h, k, h1])
  >>> grid = DiagramGrid(diagram)
  >>> print(drawer.draw(diagram, grid))
  \xymatrix{
  A \ar[r]_{f} \ar@/^1cm/[rr]^{h_{1}} & B \ar[d]^{g} & D \ar[l]^{k} \ar@/_2cm/[ll]_{h} \\
  & C &
  }
  
  The default value of ``default_curving_step`` is 4 units.
  
  See Also
  ========
  
  draw, ArrowStringDescription
class_docstr_tok: ["Given","a",":","class",":","`","~.Diagram","`","and","the","corresponding",":","class",":","`","DiagramGrid","`",",","produces","the","Xy-pic","representation","of","the","diagram",".","The","most","important","method","in","this","class","is","``","draw","``",".","Consider","the","following","triangle","diagram",":",">",">",">","from","sympy.categories","import","Object",",","NamedMorphism",",","Diagram",">",">",">","from","sympy.categories","import","DiagramGrid",",","XypicDiagramDrawer",">",">",">","A","=","Object","(","``","A","''",")",">",">",">","B","=","Object","(","``","B","''",")",">",">",">","C","=","Object","(","``","C","''",")",">",">",">","f","=","NamedMorphism","(","A",",","B",",","``","f","''",")",">",">",">","g","=","NamedMorphism","(","B",",","C",",","``","g","''",")",">",">",">","diagram","=","Diagram","(","[","f",",","g","]",",","{","g","*","f",":","``","unique","''","}",")","To","draw","this","diagram",",","its","objects","need","to","be","laid","out","with","a",":","class",":","`","DiagramGrid","`",":",":",">",">",">","grid","=","DiagramGrid","(","diagram",")","Finally",",","the","drawing",":",">",">",">","drawer","=","XypicDiagramDrawer","(",")",">",">",">","print","(","drawer.draw","(","diagram",",","grid",")",")","\\xymatrix","{","A","\\ar","[","d","]","_","{","g\\circ","f","}","\\ar","[","r","]","^","{","f","}","&","B","\\ar","[","ld","]","^","{","g","}","\\\\","C","&","}","For","further","details","see","the","docstring","of","this","method",".","To","control","the","appearance","of","the","arrows",",","formatters","are","used",".","The","dictionary","``","arrow_formatters","``","maps","morphisms","to","formatter","functions",".","A","formatter","is","accepts","an",":","class",":","`","ArrowStringDescription","`","and","is","allowed","to","modify","any","of","the","arrow","properties","exposed","thereby",".","For","example",",","to","have","all","morphisms","with","the","property","``","unique","``","appear","as","dashed","arrows",",","and","to","have","their","names","prepended","with","`","\\exists","!","`",",","the","following","should","be","done",":",">",">",">","def","formatter","(","astr",")",":","...","astr.label","=","r","''","\\exists","!","''","+","astr.label","...","astr.arrow_style","=","``","{","--",">","}","''",">",">",">","drawer.arrow_formatters","[","``","unique","''","]","=","formatter",">",">",">","print","(","drawer.draw","(","diagram",",","grid",")",")","\\xymatrix","{","A","\\ar","@","{","--",">","}","[","d","]","_","{","\\exists","!","g\\circ","f","}","\\ar","[","r","]","^","{","f","}","&","B","\\ar","[","ld","]","^","{","g","}","\\\\","C","&","}","To","modify","the","appearance","of","all","arrows","in","the","diagram",",","set","``","default_arrow_formatter","``",".","For","example",",","to","place","all","morphism","labels","a","little","bit","farther","from","the","arrow","head","so","that","they","look","more","centred",",","do","as","follows",":",">",">",">","def","default_formatter","(","astr",")",":","...","astr.label_displacement","=","``","(","0.45",")","''",">",">",">","drawer.default_arrow_formatter","=","default_formatter",">",">",">","print","(","drawer.draw","(","diagram",",","grid",")",")","\\xymatrix","{","A","\\ar","@","{","--",">","}","[","d","]","_","(","0.45",")","{","\\exists","!","g\\circ","f","}","\\ar","[","r","]","^","(","0.45",")","{","f","}","&","B","\\ar","[","ld","]","^","(","0.45",")","{","g","}","\\\\","C","&","}","In","some","diagrams","some","morphisms","are","drawn","as","curved","arrows",".","Consider","the","following","diagram",":",">",">",">","D","=","Object","(","``","D","''",")",">",">",">","E","=","Object","(","``","E","''",")",">",">",">","h","=","NamedMorphism","(","D",",","A",",","``","h","''",")",">",">",">","k","=","NamedMorphism","(","D",",","B",",","``","k","''",")",">",">",">","diagram","=","Diagram","(","[","f",",","g",",","h",",","k","]",")",">",">",">","grid","=","DiagramGrid","(","diagram",")",">",">",">","drawer","=","XypicDiagramDrawer","(",")",">",">",">","print","(","drawer.draw","(","diagram",",","grid",")",")","\\xymatrix","{","A","\\ar","[","r","]","_","{","f","}","&","B","\\ar","[","d","]","^","{","g","}","&","D","\\ar","[","l","]","^","{","k","}","\\ar","@","\/_3mm\/","[","ll","]","_","{","h","}","\\\\","&","C","&","}","To","control","how","far","the","morphisms","are","curved","by","default",",","one","can","use","the","``","unit","``","and","``","default_curving_amount","``","attributes",":",">",">",">","drawer.unit","=","``","cm","''",">",">",">","drawer.default_curving_amount","=","1",">",">",">","print","(","drawer.draw","(","diagram",",","grid",")",")","\\xymatrix","{","A","\\ar","[","r","]","_","{","f","}","&","B","\\ar","[","d","]","^","{","g","}","&","D","\\ar","[","l","]","^","{","k","}","\\ar","@","\/_1cm\/","[","ll","]","_","{","h","}","\\\\","&","C","&","}","In","some","diagrams",",","there","are","multiple","curved","morphisms","between","the","same","two","objects",".","To","control","by","how","much","the","curving","changes","between","two","such","successive","morphisms",",","use","``","default_curving_step","``",":",">",">",">","drawer.default_curving_step","=","1",">",">",">","h1","=","NamedMorphism","(","A",",","D",",","``","h1","''",")",">",">",">","diagram","=","Diagram","(","[","f",",","g",",","h",",","k",",","h1","]",")",">",">",">","grid","=","DiagramGrid","(","diagram",")",">",">",">","print","(","drawer.draw","(","diagram",",","grid",")",")","\\xymatrix","{","A","\\ar","[","r","]","_","{","f","}","\\ar","@","\/^1cm\/","[","rr","]","^","{","h_","{","1","}","}","&","B","\\ar","[","d","]","^","{","g","}","&","D","\\ar","[","l","]","^","{","k","}","\\ar","@","\/_2cm\/","[","ll","]","_","{","h","}","\\\\","&","C","&","}","The","default","value","of","``","default_curving_step","``","is","4","units",".","See","Also","========","draw",",","ArrowStringDescription"]
docstr: For a horizontal morphism, checks whether there is free space
  (i.e., space not occupied by any objects) above the morphism
  or below it.
docstr_tok: ["For","a","horizontal","morphism",",","checks","whether","there","is","free","space","(","i.e.",",","space","not","occupied","by","any","objects",")","above","the","morphism","or","below","it","."]
code: def _check_free_space_horizontal(dom_i, dom_j, cod_j, grid):
      """
      For a horizontal morphism, checks whether there is free space
      (i.e., space not occupied by any objects) above the morphism
      or below it.
      """
      if dom_j < cod_j:
          (start, end) = (dom_j, cod_j)
          backwards = False
      else:
          (start, end) = (cod_j, dom_j)
          backwards = True
  
      # Check for free space above.
      if dom_i == 0:
          free_up = True
      else:
          free_up = all(
              grid[dom_i - 1, j] for j in range(start, end + 1)
          )
  
      # Check for free space below.
      if dom_i == grid.height - 1:
          free_down = True
      else:
          free_down = not any(
              grid[dom_i + 1, j] for j in range(start, end + 1)
          )
  
      return (free_up, free_down, backwards)
  
imports: from sympy.categories import CompositeMorphism, IdentityMorphism, NamedMorphism, Diagram
  from sympy.core import Dict, Symbol, default_sort_key
  from sympy.printing.latex import latex
  from sympy.sets import FiniteSet
  from sympy.utilities.iterables import iterable
  from sympy.utilities.decorator import doctest_depends_on
  from itertools import chain
label_desc: Use image node_id 6 for calling the XypicDiagramDrawer obj's underlying member method code with example usage: obj._check_free_space_horizontal(dom_i, dom_j, cod_j, grid) and returns: free_up,  free_down,  backwards