diff --git a/docs/source/data-structures/visualisation/dot.attr.rst b/docs/source/data-structures/visualisation/dot.attr.rst new file mode 100644 index 000000000..94c484e59 --- /dev/null +++ b/docs/source/data-structures/visualisation/dot.attr.rst @@ -0,0 +1,14 @@ +.. + Copyright (c) 2024 J. D. Mitchell + + Distributed under the terms of the GPL license version 3. + + The full license is in the file LICENSE, distributed with this software. + +The Dot.Attr enum +================= + +.. autoclass:: libsemigroups_pybind11.Dot.Attr + :class-doc-from: class + :members: + :exclude-members: name diff --git a/docs/source/data-structures/visualisation/dot.kind.rst b/docs/source/data-structures/visualisation/dot.kind.rst index 9ae4b3ae0..ff5f87ee8 100644 --- a/docs/source/data-structures/visualisation/dot.kind.rst +++ b/docs/source/data-structures/visualisation/dot.kind.rst @@ -5,8 +5,8 @@ The full license is in the file LICENSE, distributed with this software. -The Dot.Kind class -================== +The Dot.Kind enum +================= .. autoclass:: libsemigroups_pybind11.Dot.Kind :class-doc-from: class diff --git a/docs/source/data-structures/visualisation/dot.rst b/docs/source/data-structures/visualisation/dot.rst index 20695d2ea..a3d03cd30 100644 --- a/docs/source/data-structures/visualisation/dot.rst +++ b/docs/source/data-structures/visualisation/dot.rst @@ -43,4 +43,4 @@ Full API .. autoclass:: Dot :class-doc-from: init :members: - :exclude-members: Kind, Node, Edge + :exclude-members: Kind, Node, Edge, Attr diff --git a/docs/source/data-structures/visualisation/index.rst b/docs/source/data-structures/visualisation/index.rst index a4292a703..7dbb2119f 100644 --- a/docs/source/data-structures/visualisation/index.rst +++ b/docs/source/data-structures/visualisation/index.rst @@ -19,6 +19,7 @@ descriptions in the DOT_ language of Graphviz_ graph drawing software. :maxdepth: 1 dot + dot.attr dot.edge dot.kind dot.node diff --git a/docs/source/main-algorithms/froidure-pin/helpers.rst b/docs/source/main-algorithms/froidure-pin/helpers.rst index 47d03a6d2..7de8b73af 100644 --- a/docs/source/main-algorithms/froidure-pin/helpers.rst +++ b/docs/source/main-algorithms/froidure-pin/helpers.rst @@ -16,6 +16,10 @@ Contents current_normal_forms current_position current_rules + dot_current_left_cayley_graph + dot_current_right_cayley_graph + dot_left_cayley_graph + dot_right_cayley_graph equal_to factorisation minimal_factorisation diff --git a/src/bipart.cpp b/src/bipart.cpp index 64fed418c..dc17a3714 100644 --- a/src/bipart.cpp +++ b/src/bipart.cpp @@ -588,6 +588,8 @@ partition* of a bipartition *f* is the partition of a subset :math:`P` of [](Bipartition& x) { return bipartition::uniform_random(x); }, py::arg("x"), R"pbdoc( +:sig=(x: Bipartition) -> None: + Replace the contents of a bipartition with a random bipartition. This function replaces the contents of the bipartition *x* with a random @@ -632,6 +634,8 @@ at random from among all bipartitions of degree equal to *deg*. [](Bipartition& x) { return bipartition::random(x); }, py::arg("x"), R"pbdoc( +:sig=(x: Bipartition) -> None: + Replace the contents of a bipartition with a random bipartition. This function replaces the contents of the bipartition *x* with a random diff --git a/src/dot.cpp b/src/dot.cpp index 476503065..85565b70a 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -49,6 +49,67 @@ its DOT_ source code string (:any:`Dot.to_string`). Write the source code to a file and render it with the Graphviz_ installation on your system. )pbdoc"); + //////////////////////////////////////////////////////////////////////////// + // Attr enum + //////////////////////////////////////////////////////////////////////////// + + py::options options; + options.disable_enum_members_docstring(); + + py::enum_ attr(dot, "Attr", R"pbdoc( +The values in this enum can be used to indicate how attribute values are +written in the DOT_ output. + +The valid values are: + +.. py:attribute:: Attr.string + :value: + + Value indicating that the attribute value should be written as a quoted + string. + +.. py:attribute:: Attr.html + :value: + + Value indicating that the attribute value should be written as an HTML-like + label. +)pbdoc"); + attr.value("string", Dot::Attr::string).value("html", Dot::Attr::html); + attr.def("__repr__", [](Dot::Attr const& val) { + return to_human_readable_repr(val, "."); + }); + + //////////////////////////////////////////////////////////////////////////// + // Kind enum + //////////////////////////////////////////////////////////////////////////// + + py::enum_ kind(dot, "Kind", R"pbdoc( +The values in this enum can be used to indicate the type of a graph. + +The valid values are: + +.. py:attribute:: Kind.digraph + :value: + + Value indicating that the represented graph has directed edges ->. + +.. py:attribute:: Kind.graph + :value: + + Value indicating that the represented graph has undirected edges --. + +.. py:attribute:: Kind.subgraph + :value: + + Value indicating that the represented graph is a subgraph of another Dot object. +)pbdoc"); + kind.value("digraph", Dot::Kind::digraph) + .value("graph", Dot::Kind::graph) + .value("subgraph", Dot::Kind::subgraph); + kind.def("__repr__", [](Dot::Kind const& knd) { + return to_human_readable_repr(knd, "."); + }); + //////////////////////////////////////////////////////////////////////////// // Node nested class //////////////////////////////////////////////////////////////////////////// @@ -74,7 +135,11 @@ The name of the node. &Dot::Node::add_attr, py::arg("key"), py::arg("val"), - R"pbdoc(Add an attribute to a node. + py::arg("kind") = Dot::Attr::string, + R"pbdoc( +:sig=(self: Dot.Node, key: str, val: str, kind: Dot.Attr = Dot.Attr.string) -> Dot.Node: + +Add an attribute to a node. This function adds a new attribute, or replaces the value of an existing attribute of a :any:`Dot.Node`. @@ -83,6 +148,8 @@ attribute of a :any:`Dot.Node`. :type key: str :param val: the value of the attribute. :type val: str +:param kind: whether to add quotes to *val* or not. +:type kind: Dot.Attr :returns: *self* :rtype: Dot.Node @@ -121,7 +188,11 @@ The name (read-only `str`) of the tail of the edge. &Dot::Edge::add_attr, py::arg("key"), py::arg("val"), - R"pbdoc(Add an attribute to an edge. + py::arg("kind") = Dot::Attr::string, + R"pbdoc( +:sig=(self: Dot.Edge, key: str, val: str, kind: Dot.Attr = Dot.Attr.string) -> Dot.Edge: + +Add an attribute to an edge. This function adds a new attribute, or replaces the value of an existing attribute of an :any:`Edge`. @@ -130,43 +201,13 @@ attribute of an :any:`Edge`. :type key: str :param val: the value of the attribute. :type val: str +:param kind: whether to add quotes to *val* or not. +:type kind: Dot.Attr :returns: *self* :rtype: Dot.Edge )pbdoc"); - //////////////////////////////////////////////////////////////////////////// - // Kind enum - //////////////////////////////////////////////////////////////////////////// - py::options options; - options.disable_enum_members_docstring(); - py::enum_ kind(dot, "Kind", R"pbdoc( -The values in this enum can be used to indicate the type of a graph. - -The valid values are: - -.. py:attribute:: Kind.digraph - :value: - - Value indicating that the represented graph has directed edges ->. - -.. py:attribute:: Kind.graph - :value: - - Value indicating that the represented graph has undirected edges --. - -.. py:attribute:: Kind.subgraph - :value: - - Value indicating that the represented graph is a subgraph of another Dot object. -)pbdoc"); - kind.value("digraph", Dot::Kind::digraph) - .value("graph", Dot::Kind::graph) - .value("subgraph", Dot::Kind::subgraph); - kind.def("__repr__", [](Dot::Kind const& knd) { - return to_human_readable_repr(knd, "."); - }); - //////////////////////////////////////////////////////////////////////////// // Dot members //////////////////////////////////////////////////////////////////////////// @@ -474,7 +515,11 @@ representation of the graph in the DOT_ language for Graphviz_. &Dot::add_attr, py::arg("key"), py::arg("val"), - R"pbdoc(Add an attribute to a :any:`Dot` object. + py::arg("kind") = Dot::Attr::string, + R"pbdoc( +:sig=(self: Dot, key: str, val: str, kind: Dot.Attr = Dot.Attr.string) -> Dot: + +Add an attribute to a :any:`Dot` object. This function adds a new attribute, or replaces the value of an existing attribute of an :any:`Dot`. @@ -483,6 +528,8 @@ attribute of an :any:`Dot`. :type key: str :param val: the value of the attribute. :type val: str +:param kind: whether to add quotes to *val* or not. +:type kind: Dot.Attr :returns: *self* :rtype: Dot @@ -492,7 +539,10 @@ attribute of an :any:`Dot`. dot.def("add_attr", &Dot::add_attr, py::arg("key"), - R"pbdoc(Add an attribute to a :any:`Dot` object. + R"pbdoc( +:sig=(self: Dot, key: str) -> Dot: + +Add an attribute to a :any:`Dot` object. This function adds a new attribute, or replaces the value of an existing attribute of an :any:`Dot`. diff --git a/src/froidure-pin-base.cpp b/src/froidure-pin-base.cpp index f95e40ae9..40904d1d6 100644 --- a/src/froidure-pin-base.cpp +++ b/src/froidure-pin-base.cpp @@ -17,6 +17,7 @@ // // libsemigroups headers +#include #include // pybind11.... @@ -524,16 +525,170 @@ Returns the position of the suffix of the element ``x`` in position *pos* // Helper functions //////////////////////////////////////////////////////////////////////// - { - py::options options; - options.disable_function_signatures(); + m.def("froidure_pin_dot_current_right_cayley_graph", + py::overload_cast( + &froidure_pin::dot_current_right_cayley_graph), + py::arg("fp"), + R"pbdoc( +:sig=(fp: FroidurePin) -> Dot: + +Returns a :any:`Dot` object representing the current right Cayley graph. + +This function does not trigger a full enumeration of *fp*. + +:param fp: the :any:`FroidurePin` object. +:type fp: FroidurePin + +:returns: A :any:`Dot` object. +:rtype: Dot +)pbdoc"); + + m.def("froidure_pin_dot_current_right_cayley_graph", + py::overload_cast( + &froidure_pin::dot_current_right_cayley_graph), + py::arg("fp"), + py::arg("gen_names"), + R"pbdoc( +:sig=(fp: FroidurePin, gen_names: str) -> Dot: + +Returns a :any:`Dot` object representing the current right Cayley graph. + +The generators are labelled using the characters in *gen_names*. + +:param fp: the :any:`FroidurePin` object. +:type fp: FroidurePin +:param gen_names: the labels for the generators. +:type gen_names: str + +:returns: A :any:`Dot` object. +:rtype: Dot +)pbdoc"); + + m.def("froidure_pin_dot_right_cayley_graph", + py::overload_cast( + &froidure_pin::dot_right_cayley_graph), + py::arg("fp"), + R"pbdoc( +:sig=(fp: FroidurePin) -> Dot: + +Returns a :any:`Dot` object representing the right Cayley graph. + +This function triggers a full enumeration of *fp*. + +:param fp: the :any:`FroidurePin` object. +:type fp: FroidurePin + +:returns: A :any:`Dot` object. +:rtype: Dot +)pbdoc"); + + m.def("froidure_pin_dot_right_cayley_graph", + py::overload_cast( + &froidure_pin::dot_right_cayley_graph), + py::arg("fp"), + py::arg("gen_names"), + R"pbdoc( +:sig=(fp: FroidurePin, gen_names: str) -> Dot: + +Returns a :any:`Dot` object representing the right Cayley graph. + +This function triggers a full enumeration of *fp*. The generators are labelled +using the characters in *gen_names*. + +:param fp: the :any:`FroidurePin` object. +:type fp: FroidurePin +:param gen_names: the labels for the generators. +:type gen_names: str + +:returns: A :any:`Dot` object. +:rtype: Dot +)pbdoc"); + + m.def("froidure_pin_dot_current_left_cayley_graph", + py::overload_cast( + &froidure_pin::dot_current_left_cayley_graph), + py::arg("fp"), + R"pbdoc( +:sig=(fp: FroidurePin) -> Dot: + +Returns a :any:`Dot` object representing the current left Cayley graph. + +This function does not trigger a full enumeration of *fp*. + +:param fp: the :any:`FroidurePin` object. +:type fp: FroidurePin + +:returns: A :any:`Dot` object. +:rtype: Dot +)pbdoc"); + + m.def("froidure_pin_dot_current_left_cayley_graph", + py::overload_cast( + &froidure_pin::dot_current_left_cayley_graph), + py::arg("fp"), + py::arg("gen_names"), + R"pbdoc( +:sig=(fp: FroidurePin, gen_names: str) -> Dot: - m.def("froidure_pin_product_by_reduction", - &froidure_pin::product_by_reduction, - py::arg("fp"), - py::arg("i"), - py::arg("j"), - R"pbdoc( +Returns a :any:`Dot` object representing the current left Cayley graph. + +The generators are labelled using the characters in *gen_names*. + +:param fp: the :any:`FroidurePin` object. +:type fp: FroidurePin +:param gen_names: the labels for the generators. +:type gen_names: str + +:returns: A :any:`Dot` object. +:rtype: Dot +)pbdoc"); + + m.def("froidure_pin_dot_left_cayley_graph", + py::overload_cast( + &froidure_pin::dot_left_cayley_graph), + py::arg("fp"), + R"pbdoc( +:sig=(fp: FroidurePin) -> Dot: + +Returns a :any:`Dot` object representing the left Cayley graph. + +This function triggers a full enumeration of *fp*. + +:param fp: the :any:`FroidurePin` object. +:type fp: FroidurePin + +:returns: A :any:`Dot` object. +:rtype: Dot +)pbdoc"); + + m.def("froidure_pin_dot_left_cayley_graph", + py::overload_cast( + &froidure_pin::dot_left_cayley_graph), + py::arg("fp"), + py::arg("gen_names"), + R"pbdoc( +:sig=(fp: FroidurePin, gen_names: str) -> Dot: + +Returns a :any:`Dot` object representing the left Cayley graph. + +This function triggers a full enumeration of *fp*. The generators are labelled +using the characters in *gen_names*. + +:param fp: the :any:`FroidurePin` object. +:type fp: FroidurePin +:param gen_names: the labels for the generators. +:type gen_names: str + +:returns: A :any:`Dot` object. +:rtype: Dot +)pbdoc"); + + m.def("froidure_pin_product_by_reduction", + &froidure_pin::product_by_reduction, + py::arg("fp"), + py::arg("i"), + py::arg("j"), + R"pbdoc( :sig=(fp: FroidurePin, i: int, j: int) -> int: Compute a product using the Cayley graph. @@ -574,15 +729,14 @@ path in the left Cayley graph from *j* labelled by ``minimal_factorisation(fp, i)`` and ``minimal_factorisation(fp, j)``. )pbdoc"); - m.def( - "froidure_pin_current_minimal_factorisation", - [](FroidurePinBase const& fp, - FroidurePinBase::element_index_type pos) { - return froidure_pin::current_minimal_factorisation(fp, pos); - }, - py::arg("fp"), - py::arg("pos"), - R"pbdoc( + m.def( + "froidure_pin_current_minimal_factorisation", + [](FroidurePinBase const& fp, FroidurePinBase::element_index_type pos) { + return froidure_pin::current_minimal_factorisation(fp, pos); + }, + py::arg("fp"), + py::arg("pos"), + R"pbdoc( :sig=(fp: FroidurePin, pos: int) -> list[int]: Returns the short-lex least word representing an element given by index. @@ -611,22 +765,22 @@ This function returns the short-lex least word (in the generators) representing No enumeration is triggered by calling this function. )pbdoc"); - // The following function is documented in src/froidure-pin.cpp - m.def( - "froidure_pin_minimal_factorisation", - [](FroidurePinBase& fp, FroidurePinBase::element_index_type pos) { - return froidure_pin::minimal_factorisation(fp, pos); - }, - py::arg("fp"), - py::arg("pos")); - - m.def( - "froidure_pin_current_normal_forms", - [](FroidurePinBase const& fp) { - return py::make_iterator(fp.cbegin_current_normal_forms(), - fp.cend_current_normal_forms()); - }, - R"pbdoc( + // The following function is documented in src/froidure-pin.cpp + m.def( + "froidure_pin_minimal_factorisation", + [](FroidurePinBase& fp, FroidurePinBase::element_index_type pos) { + return froidure_pin::minimal_factorisation(fp, pos); + }, + py::arg("fp"), + py::arg("pos")); + + m.def( + "froidure_pin_current_normal_forms", + [](FroidurePinBase const& fp) { + return py::make_iterator(fp.cbegin_current_normal_forms(), + fp.cend_current_normal_forms()); + }, + R"pbdoc( :sig=(fp: FroidurePin) -> collections.abc.Iterator[list[int]]: Returns an iterator yielding the so-far enumerated normal forms (if any). @@ -650,13 +804,13 @@ complete set of normal forms, then use :any:`normal_forms` instead. Constant. )pbdoc"); - m.def( - "froidure_pin_current_rules", - [](FroidurePinBase const& fp) { - return py::make_iterator(fp.cbegin_current_rules(), - fp.cend_current_rules()); - }, - R"pbdoc( + m.def( + "froidure_pin_current_rules", + [](FroidurePinBase const& fp) { + return py::make_iterator(fp.cbegin_current_rules(), + fp.cend_current_rules()); + }, + R"pbdoc( :sig=(fp: FroidurePin) -> collections.abc.Iterator[tuple[list[int], list[int]]]: Returns an iterator yielding the so-far enumerated rules. @@ -717,13 +871,13 @@ to obtain the complete set of rules, then use :any:`rules` instead. ([3, 3], [3])] )pbdoc"); - m.def( - "froidure_pin_normal_forms", - [](FroidurePinBase& fp) { - return py::make_iterator(fp.cbegin_normal_forms(), - fp.cend_normal_forms()); - }, - R"pbdoc( + m.def( + "froidure_pin_normal_forms", + [](FroidurePinBase& fp) { + return py::make_iterator(fp.cbegin_normal_forms(), + fp.cend_normal_forms()); + }, + R"pbdoc( :sig=(fp: FroidurePin) -> collections.abc.Iterator[list[int]]: Returns an iterator yielding normal forms. This function returns an iterator @@ -743,12 +897,12 @@ then use :any:`current_normal_forms` instead. collections.abc.Iterator[list[int]] )pbdoc"); - m.def( - "froidure_pin_rules", - [](FroidurePinBase& fp) { - return py::make_iterator(fp.cbegin_rules(), fp.cend_rules()); - }, - R"pbdoc( + m.def( + "froidure_pin_rules", + [](FroidurePinBase& fp) { + return py::make_iterator(fp.cbegin_rules(), fp.cend_rules()); + }, + R"pbdoc( :sig=(fp: FroidurePin) -> collections.abc.Iterator[tuple[list[int], list[int]]]: Returns an iterator yielding the rules. @@ -769,6 +923,5 @@ use :any:`current_rules` instead. :rtype: collections.abc.Iterator[tuple[list[int], list[int]]] )pbdoc"); - } } // init_froidure_pin_base } // namespace libsemigroups diff --git a/src/libsemigroups_pybind11/froidure_pin.py b/src/libsemigroups_pybind11/froidure_pin.py index b77740bad..6a216784f 100644 --- a/src/libsemigroups_pybind11/froidure_pin.py +++ b/src/libsemigroups_pybind11/froidure_pin.py @@ -75,6 +75,10 @@ froidure_pin_current_normal_forms as _froidure_pin_current_normal_forms, froidure_pin_current_position as _froidure_pin_current_position, froidure_pin_current_rules as _froidure_pin_current_rules, + froidure_pin_dot_current_left_cayley_graph as _froidure_pin_dot_current_left_cayley_graph, + froidure_pin_dot_current_right_cayley_graph as _froidure_pin_dot_current_right_cayley_graph, + froidure_pin_dot_left_cayley_graph as _froidure_pin_dot_left_cayley_graph, + froidure_pin_dot_right_cayley_graph as _froidure_pin_dot_right_cayley_graph, froidure_pin_equal_to as _froidure_pin_equal_to, froidure_pin_factorisation as _froidure_pin_factorisation, froidure_pin_minimal_factorisation as _froidure_pin_minimal_factorisation, @@ -261,6 +265,10 @@ def sorted_elements( # pylint: disable=missing-function-docstring # TODO(1) be good to get the notes about enumeration being triggered or not, in # this doc +dot_current_left_cayley_graph = _wrap_cxx_free_fn(_froidure_pin_dot_current_left_cayley_graph) +dot_current_right_cayley_graph = _wrap_cxx_free_fn(_froidure_pin_dot_current_right_cayley_graph) +dot_left_cayley_graph = _wrap_cxx_free_fn(_froidure_pin_dot_left_cayley_graph) +dot_right_cayley_graph = _wrap_cxx_free_fn(_froidure_pin_dot_right_cayley_graph) current_minimal_factorisation = _wrap_cxx_free_fn(_froidure_pin_current_minimal_factorisation) current_normal_forms = _wrap_cxx_free_fn(_froidure_pin_current_normal_forms) current_position = _wrap_cxx_free_fn(_froidure_pin_current_position) diff --git a/tests/test_dot.py b/tests/test_dot.py index 30e1df64f..65c8f1286 100644 --- a/tests/test_dot.py +++ b/tests/test_dot.py @@ -23,11 +23,11 @@ def test_edge(): assert len(edges) == 6 assert edges[0].head == "0" assert edges[0].tail == "0" - assert edges[0].attrs == {"color": "#00ff00"} + assert edges[0].attrs == {"color": '"#00ff00"'} edges[0].add_attr("style", "dashed") - assert edges[0].attrs == {"color": "#00ff00", "style": "dashed"} + assert edges[0].attrs == {"color": '"#00ff00"', "style": '"dashed"'} edges[0].attrs["color"] = "blue" # FIXME this should throw - assert edges[0].attrs == {"color": "#00ff00", "style": "dashed"} + assert edges[0].attrs == {"color": '"#00ff00"', "style": '"dashed"'} def test_node(): @@ -36,11 +36,11 @@ def test_node(): nodes = d.nodes() assert len(nodes) == 3 assert nodes[0].name == "0" - assert nodes[0].attrs == {"shape": "box"} + assert nodes[0].attrs == {"shape": '"box"'} nodes[0].add_attr("shape", "circle") - assert nodes[0].attrs == {"shape": "circle"} + assert nodes[0].attrs == {"shape": '"circle"'} nodes[0].attrs["color"] = "blue" # FIXME this should throw - assert nodes[0].attrs == {"shape": "circle"} + assert nodes[0].attrs == {"shape": '"circle"'} def test_dot_copy(): @@ -55,9 +55,9 @@ def test_dot_attrs(): d.add_attr("node [shape=circle]") assert d.attrs() == {"node [shape=circle]": ""} d.add_attr("splines", "line") - assert d.attrs() == {"node [shape=circle]": "", "splines": "line"} + assert d.attrs() == {"node [shape=circle]": "", "splines": '"line"'} del d.attrs()["splines"] # TODO(1) should raise - assert d.attrs() == {"node [shape=circle]": "", "splines": "line"} + assert d.attrs() == {"node [shape=circle]": "", "splines": '"line"'} def test_dot_add_node(): @@ -81,7 +81,7 @@ def test_dot_add_edge(): assert len(d.edges()) == 1 assert e.attrs == {} e.add_attr("color", "#00FF00") - assert e.attrs == {"color": "#00FF00"} + assert e.attrs == {"color": '"#00FF00"'} def test_dot_add_subgraph(): @@ -142,6 +142,23 @@ def test_dot_kind(): assert d.kind() == Dot.Kind.graph +def test_dot_attr(): + d = Dot() + d.add_attr("label", "pets", Dot.Attr.string) + d.add_node("cat").add_attr("label", "cat", Dot.Attr.html) + d.add_node("dog") + d.add_edge("cat", "dog").add_attr("label", "friend", Dot.Attr.string) + + assert repr(Dot.Attr.string) == "" + assert d.attrs() == {"label": '"pets"'} + assert d.node("cat").attrs == {"label": "cat"} + assert d.edge("cat", "dog").attrs == {"label": '"friend"'} + assert d.to_string() == ( + 'digraph {\n label="pets"\n cat [label=cat]\n dog\n ' + 'cat -> dog [label="friend"]\n}' + ) + + def test_dot_return_policy(): d = Dot() assert d.colors is not d.colors diff --git a/tests/test_froidure_pin.py b/tests/test_froidure_pin.py index eea7d86f5..7f3d8a883 100644 --- a/tests/test_froidure_pin.py +++ b/tests/test_froidure_pin.py @@ -18,6 +18,7 @@ UNDEFINED, Bipartition, BMat8, + Dot, FroidurePin, KnuthBendix, LibsemigroupsError, @@ -161,13 +162,50 @@ def check_idempotents(S): def check_cayley_graphs(S): ReportGuard(False) + gen_names = "abcdefghijklmnopqrstuvwxyz"[: S.number_of_generators()] + + d = froidure_pin.dot_current_right_cayley_graph(S) + assert isinstance(d, Dot) + assert d.kind() == Dot.Kind.digraph + assert len(d.nodes()) == S.current_size() + 2 + + d = froidure_pin.dot_current_right_cayley_graph(S, gen_names) + assert isinstance(d, Dot) + assert len(d.nodes()) == S.current_size() + 2 + + d = froidure_pin.dot_current_left_cayley_graph(S) + assert isinstance(d, Dot) + assert d.kind() == Dot.Kind.digraph + assert len(d.nodes()) == S.current_size() + 2 + + d = froidure_pin.dot_current_left_cayley_graph(S, gen_names) + assert isinstance(d, Dot) + assert len(d.nodes()) == S.current_size() + 2 + g = S.right_cayley_graph() assert g.number_of_nodes() == S.size() assert g.out_degree() == S.number_of_generators() + + d = froidure_pin.dot_right_cayley_graph(S) + assert isinstance(d, Dot) + assert len(d.nodes()) == S.size() + 2 + + d = froidure_pin.dot_right_cayley_graph(S, gen_names) + assert isinstance(d, Dot) + assert len(d.nodes()) == S.size() + 2 + g = S.left_cayley_graph() assert g.number_of_nodes() == S.size() assert g.out_degree() == S.number_of_generators() + d = froidure_pin.dot_left_cayley_graph(S) + assert isinstance(d, Dot) + assert len(d.nodes()) == S.size() + 2 + + d = froidure_pin.dot_left_cayley_graph(S, gen_names) + assert isinstance(d, Dot) + assert len(d.nodes()) == S.size() + 2 + def check_factor_prod_rels(S): ReportGuard(False)