Skip to content

Commit

Permalink
Add four simple layouts (#310)
Browse files Browse the repository at this point in the history
The four simplest layouts were added: bipartite, circular, shell, and spiral. The
layout functions return the new type Pos2DMapping

Related to #280

* bipartite + circular

* add shell and spiral layouts

* tests

* release note

* release note newline

* add api

* resolve conflicts

* clippy

* flake8

* fix bipartite empty issue

* fix api

* fix bipartite doc issue

* Update retworkx/__init__.py

Co-authored-by: georgios-ts <45130028+georgios-ts@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: georgios-ts <45130028+georgios-ts@users.noreply.github.com>

* handle index holes + minor fixes

* rename layouts to layout

* add hole tests

* lints

* resolve conflicts

* black reformatted

* add f64 type declaration

* fix bipartite invalid dy

* fix shell index holes

Co-authored-by: georgios-ts <45130028+georgios-ts@users.noreply.github.com>

* lint

* add hole test cases that specify shells

* lim range check

* Update layout tests to use custom assertion method

This commit adds a new custom assertion method for comparing layouts
with a tolerance (fixed at 1e-6) ensuring that no layout differs from
the expected in any coordinate by more than this. If there is a failure
it will print a detailed message about which node differs from the
expected. With this change locally 2 bipartite layout tests failed so
this commit updates the expected values so it passes (the layouts still
look like valid bipartite layouts just the center point was different).

* Fix lint

Co-authored-by: georgios-ts <45130028+georgios-ts@users.noreply.github.com>
Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
  • Loading branch information
3 people authored May 31, 2021
1 parent aad90f7 commit ab1f984
Show file tree
Hide file tree
Showing 7 changed files with 1,504 additions and 5 deletions.
16 changes: 16 additions & 0 deletions docs/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ type functions in the algorithms API but can be run with a
retworkx.transitivity
retworkx.core_number
retworkx.random_layout
retworkx.bipartite_layout
retworkx.circular_layout
retworkx.shell_layout
retworkx.spiral_layout
retworkx.spring_layout

.. _layout-functions:
Expand All @@ -157,6 +161,18 @@ Layout Functions
retworkx.spring_layout
retworkx.graph_random_layout
retworkx.digraph_random_layout
retworkx.bipartite_layout
retworkx.graph_bipartite_layout
retworkx.digraph_bipartite_layout
retworkx.circular_layout
retworkx.graph_circular_layout
retworkx.digraph_circular_layout
retworkx.shell_layout
retworkx.graph_shell_layout
retworkx.digraph_shell_layout
retworkx.spiral_layout
retworkx.graph_spiral_layout
retworkx.digraph_spiral_layout

Converters
----------
Expand Down
6 changes: 6 additions & 0 deletions releasenotes/notes/simple-layouts-93db8f7f5fa1fe83.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
features:
- |
Four simple layouts were added: :func:`~retworkx.bipartite_layout`,
:func:`~retworkx.circular_layout`, :func:`~retworkx.shell_layout`,
and :func:`~retworkx.spiral_layout`.
177 changes: 177 additions & 0 deletions retworkx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1046,3 +1046,180 @@ def networkx_converter(graph):
]
)
return new_graph


@functools.singledispatch
def bipartite_layout(
graph,
first_nodes,
horizontal=False,
scale=1,
center=None,
aspect_ratio=4 / 3,
):
"""Generate a bipartite layout of the graph
:param graph: The graph to generate the layout for. Can either be a
:class:`~retworkx.PyGraph` or :class:`~retworkx.PyDiGraph`
:param set first_nodes: The set of node indexes on the left (or top if
horitontal is true)
:param bool horizontal: An optional bool specifying the orientation of the
layout
:param float scale: An optional scaling factor to scale positions
:param tuple center: An optional center position. This is a 2 tuple of two
``float`` values for the center position
:param float aspect_ratio: An optional number for the ratio of the width to
the height of the layout.
:returns: The bipartite layout of the graph.
:rtype: Pos2DMapping
"""
raise TypeError("Invalid Input Type %s for graph" % type(graph))


@bipartite_layout.register(PyDiGraph)
def _digraph_bipartite_layout(
graph,
first_nodes,
horizontal=False,
scale=1,
center=None,
aspect_ratio=4 / 3,
):
return digraph_bipartite_layout(
graph,
first_nodes,
horizontal=horizontal,
scale=scale,
center=center,
aspect_ratio=aspect_ratio,
)


@bipartite_layout.register(PyGraph)
def _graph_bipartite_layout(
graph,
first_nodes,
horizontal=False,
scale=1,
center=None,
aspect_ratio=4 / 3,
):
return graph_bipartite_layout(
graph,
first_nodes,
horizontal=horizontal,
scale=scale,
center=center,
aspect_ratio=aspect_ratio,
)


@functools.singledispatch
def circular_layout(graph, scale=1, center=None):
"""Generate a circular layout of the graph
:param graph: The graph to generate the layout for. Can either be a
:class:`~retworkx.PyGraph` or :class:`~retworkx.PyDiGraph`
:param float scale: An optional scaling factor to scale positions
:param tuple center: An optional center position. This is a 2 tuple of two
``float`` values for the center position
:returns: The circular layout of the graph.
:rtype: Pos2DMapping
"""
raise TypeError("Invalid Input Type %s for graph" % type(graph))


@circular_layout.register(PyDiGraph)
def _digraph_circular_layout(graph, scale=1, center=None):
return digraph_circular_layout(graph, scale=scale, center=center)


@circular_layout.register(PyGraph)
def _graph_circular_layout(graph, scale=1, center=None):
return graph_circular_layout(graph, scale=scale, center=center)


@functools.singledispatch
def shell_layout(graph, nlist=None, rotate=None, scale=1, center=None):
"""
Generate a shell layout of the graph
:param graph: The graph to generate the layout for. Can either be a
:class:`~retworkx.PyGraph` or :class:`~retworkx.PyDiGraph`
:param list nlist: The list of lists of indexes which represents each shell
:param float rotate: Angle (in radians) by which to rotate the starting
position of each shell relative to the starting position of the
previous shell
:param float scale: An optional scaling factor to scale positions
:param tuple center: An optional center position. This is a 2 tuple of two
``float`` values for the center position
:returns: The shell layout of the graph.
:rtype: Pos2DMapping
"""
raise TypeError("Invalid Input Type %s for graph" % type(graph))


@shell_layout.register(PyDiGraph)
def _digraph_shell_layout(graph, nlist=None, rotate=None, scale=1, center=None):
return digraph_shell_layout(
graph, nlist=nlist, rotate=rotate, scale=scale, center=center
)


@shell_layout.register(PyGraph)
def _graph_shell_layout(graph, nlist=None, rotate=None, scale=1, center=None):
return graph_shell_layout(
graph, nlist=nlist, rotate=rotate, scale=scale, center=center
)


@functools.singledispatch
def spiral_layout(
graph, scale=1, center=None, resolution=0.35, equidistant=False
):
"""
Generate a spiral layout of the graph
:param graph: The graph to generate the layout for. Can either be a
:class:`~retworkx.PyGraph` or :class:`~retworkx.PyDiGraph`
:param float scale: An optional scaling factor to scale positions
:param tuple center: An optional center position. This is a 2 tuple of two
``float`` values for the center position
:param float resolution: The compactness of the spiral layout returned.
Lower values result in more compressed spiral layouts.
:param bool equidistant: If true, nodes will be plotted equidistant from
each other.
:returns: The spiral layout of the graph.
:rtype: Pos2DMapping
"""
raise TypeError("Invalid Input Type %s for graph" % type(graph))


@spiral_layout.register(PyDiGraph)
def _digraph_spiral_layout(
graph, scale=1, center=None, resolution=0.35, equidistant=False
):
return digraph_spiral_layout(
graph,
scale=scale,
center=center,
resolution=resolution,
equidistant=equidistant,
)


@spiral_layout.register(PyGraph)
def _graph_spiral_layout(
graph, scale=1, center=None, resolution=0.35, equidistant=False
):
return graph_spiral_layout(
graph,
scale=scale,
center=center,
resolution=resolution,
equidistant=equidistant,
)
Loading

0 comments on commit ab1f984

Please sign in to comment.