diff --git a/src/Semigroups.jl b/src/Semigroups.jl index 6ed0f09..0086c25 100644 --- a/src/Semigroups.jl +++ b/src/Semigroups.jl @@ -87,12 +87,7 @@ include("transf.jl") # Algorithm types (must come after element types) include("froidure-pin.jl") -include("to-cong.jl") -include("to-todd-coxeter.jl") -include("to-presentation.jl") -include("to-knuth-bendix.jl") -include("to-froidure-pin.jl") -include("to-inverse-presentation.jl") +include("to.jl") function _version_string(v::Union{Nothing,VersionNumber}) return isnothing(v) ? "unknown" : string(v) diff --git a/src/to-cong.jl b/src/to-cong.jl deleted file mode 100644 index 985ce65..0000000 --- a/src/to-cong.jl +++ /dev/null @@ -1,40 +0,0 @@ -""" -to-cong.jl - conversions to Congruence -""" - -""" - to(::Type{Congruence}, kind::congruence_kind, fp::FroidurePin, - wg) -> Congruence - -Convert a Froidure-Pin graph to a Congruence. - -Julia implementation of libsemigroups' `to(kind, fp, wg)` -conversion. `wg` must be either the left or right Cayley graph of `fp`. -The result represents the trivial congruence over the semigroup defined by -`fp`. - -`kind` selects whether the resulting congruence is one-sided or two-sided. - -# Throws - -- [`LibsemigroupsError`](@ref Semigroups.LibsemigroupsError) if `wg` is not - the left or right Cayley graph of `fp`. -""" -to(::Type{Congruence}, kind::congruence_kind, fp::FroidurePin, wg) = - @wrap_libsemigroups_call LibSemigroups.to_congruence_from_fpb(kind, fp.cxx_obj, wg) - -""" - to(::Type{Congruence}, kind::congruence_kind, wg::WordGraph) -> Congruence - -Convert a WordGraph to a Congruence. - -Julia implementation of libsemigroups' `to(kind, wg)` -conversion. The result represents the trivial congruence over `wg`. - -`kind` selects whether the resulting congruence is one-sided or two-sided. - -The graph is added to the constructed congruence as-is; no checks are made -that the resulting Todd-Coxeter or Congruence object is valid. -""" -@cxxdereference to(::Type{Congruence}, kind::congruence_kind, wg::WordGraph) = - @wrap_libsemigroups_call LibSemigroups.to_congruence_from_wg(kind, wg) diff --git a/src/to-froidure-pin.jl b/src/to-froidure-pin.jl deleted file mode 100644 index 5dfa941..0000000 --- a/src/to-froidure-pin.jl +++ /dev/null @@ -1,24 +0,0 @@ -""" -to-froidure-pin.jl - conversions to FroidurePin -""" - -""" - to(::Type{FroidurePin}, wg::WordGraph) -> FroidurePin{Transf{UInt32}} - -Convert a complete `WordGraph` to a Froidure-Pin whose elements are -`Transf{UInt32}`. This is the Julia implementation of -libsemigroups' `to(wg)` conversion. Each graph label becomes a -transformation generator, with the transformation image determined by the -edge target for each node. - -The graph must be complete, and every target must be a node of the graph. - -# Throws - -- [`LibsemigroupsError`](@ref Semigroups.LibsemigroupsError) if the graph is - incomplete or contains an out-of-range target. -""" -@cxxdereference to(::Type{FroidurePin}, wg::WordGraph) = - FroidurePin{Transf{UInt32}}(@wrap_libsemigroups_call begin - LibSemigroups.to_froidure_pin_from_wg(wg) - end) diff --git a/src/to-inverse-presentation.jl b/src/to-inverse-presentation.jl deleted file mode 100644 index a4726b1..0000000 --- a/src/to-inverse-presentation.jl +++ /dev/null @@ -1,25 +0,0 @@ -""" -to-inverse-presentation.jl - conversions to InversePresentation -""" - -""" - to(::Type{InversePresentation}, p::Presentation) -> InversePresentation - -Convert a Presentation to an InversePresentation. - -Julia implementation of libsemigroups' `to(p)` -conversion. The resulting inverse presentation has rules equivalent to -those of `p`, over a normalised alphabet with a corresponding inverse -letter for each letter of `p`. -""" -to(::Type{InversePresentation}, p::Presentation) = - @wrap_libsemigroups_call LibSemigroups.to_inverse_presentation_word(p) - -""" - to(::Type{InversePresentation}, ip::InversePresentation) -> InversePresentation - -Convert an InversePresentation to an InversePresentation. - -Return a copy of `ip`. -""" -to(::Type{InversePresentation}, ip::InversePresentation) = InversePresentation(ip) diff --git a/src/to-knuth-bendix.jl b/src/to-knuth-bendix.jl deleted file mode 100644 index afccb67..0000000 --- a/src/to-knuth-bendix.jl +++ /dev/null @@ -1,27 +0,0 @@ -""" -to-knuth-bendix.jl - conversions to KnuthBendix -""" - -""" - to(::Type{KnuthBendix}, kind::congruence_kind, fp::FroidurePin) -> KnuthBendix - -Julia implementation of libsemigroups' `to(kind, fp)` -conversion. It constructs a Knuth-Bendix instance from the presentation -obtained from `fp` and represents the trivial congruence over that semigroup. -`kind` selects whether the resulting congruence is one-sided or two-sided. - -This conversion enumerates `fp` before obtaining its presentation. -""" -to(::Type{KnuthBendix}, kind::congruence_kind, fp::FroidurePin) = - LibSemigroups.to_knuth_bendix_from_fpb(kind, fp.cxx_obj) - -""" - to(::Type{KnuthBendix}, kind::congruence_kind, tc::ToddCoxeter) -> KnuthBendix - -Julia implementation of libsemigroups' `to(kind, tc)` -conversion. It constructs a Knuth-Bendix instance from `tc.presentation()` -and represents the trivial congruence over the semigroup defined by `tc`. -`kind` selects whether the resulting congruence is one-sided or two-sided. -""" -to(::Type{KnuthBendix}, kind::congruence_kind, tc::ToddCoxeter) = - LibSemigroups.to_knuth_bendix_from_tc(kind, tc) diff --git a/src/to-presentation.jl b/src/to-presentation.jl deleted file mode 100644 index 2c9d9d3..0000000 --- a/src/to-presentation.jl +++ /dev/null @@ -1,66 +0,0 @@ -""" -to-presentation.jl - to Presentation conversion -""" - -""" - to(::Type{Presentation}, p::Presentation) -> Presentation - -Julia implementation of the identity conversion for `Presentation`. The -returned presentation is a copy of `p`. -""" -to(::Type{Presentation}, p::Presentation) = Presentation(p) - -""" - to(::Type{Presentation}, c::Congruence) -> Presentation - -Julia implementation of libsemigroups' `to(c)` conversion. -Return the presentation used to construct or initialise `c`. - -This conversion returns the presentation used to construct or initialise `c`. -Congruence-generating pairs are not added to the returned presentation by -running `c`. -""" -to(::Type{Presentation}, c::Congruence) = LibSemigroups.to_presentation_word(c) - -""" - to(::Type{Presentation}, k::Kambites) -> Presentation - -Julia implementation of libsemigroups' `to(k)` conversion. -Return a presentation equivalent to the presentation used to construct or -initialise `k`. - -This conversion does not enumerate `k`. -""" -to(::Type{Presentation}, k::Kambites) = LibSemigroups.to_presentation_word(k) - -""" - to(::Type{Presentation}, tc::ToddCoxeter) -> Presentation - -Julia implementation of libsemigroups' `to(tc)` conversion. -Return the presentation used to construct or initialise `tc`. - -This conversion does not enumerate `tc`. -""" -to(::Type{Presentation}, tc::ToddCoxeter) = LibSemigroups.to_presentation_word(tc) - -""" - to(::Type{Presentation}, kb::KnuthBendix) -> Presentation - -Julia implementation of libsemigroups' `to(kb)` conversion. -Return a presentation using the currently active rules of `kb`. - -This conversion does not enumerate `kb`, so the returned presentation may not -yet describe the completed semigroup or monoid. Run `kb` first if a fully -processed presentation is required. -""" -to(::Type{Presentation}, kb::KnuthBendix) = LibSemigroups.to_presentation_word(kb) - -""" - to(::Type{Presentation}, fp::FroidurePin) -> Presentation - -Julia implementation of libsemigroups' `to(fp)` conversion. -Return a presentation using the currently known rules of `fp`. - -This conversion enumerates `fp` before obtaining its presentation. -""" -to(::Type{Presentation}, fp::FroidurePin) = LibSemigroups.to_presentation_word(fp.cxx_obj) diff --git a/src/to-todd-coxeter.jl b/src/to-todd-coxeter.jl deleted file mode 100644 index 4dfc4b2..0000000 --- a/src/to-todd-coxeter.jl +++ /dev/null @@ -1,42 +0,0 @@ -""" -to-todd-coxeter.jl - conversions to ToddCoxeter -""" - -""" - to(::Type{ToddCoxeter}, kind::congruence_kind, fp::FroidurePin, - wg::WordGraph) -> ToddCoxeter - -Convert a Froidure-Pin graph to a Todd-Coxeter. - -Julia implementation of libsemigroups' `to(kind, fp, wg)` -conversion. `wg` must be either the left or right Cayley graph of `fp`. -The result represents the trivial congruence over the semigroup defined by -`fp`. -`kind` selects whether the resulting congruence is one-sided or two-sided. - -# Throws - -- [`LibsemigroupsError`](@ref Semigroups.LibsemigroupsError) if `wg` is not - the left or right Cayley graph of `fp`. -""" -to(::Type{ToddCoxeter}, kind::congruence_kind, fp::FroidurePin, wg) = - @wrap_libsemigroups_call LibSemigroups.to_todd_coxeter_from_fpb(kind, fp.cxx_obj, wg) - -""" - to(::Type{ToddCoxeter}, kind::congruence_kind, kb::KnuthBendix) -> ToddCoxeter - -Convert a Knuth-Bendix to a Todd-Coxeter. - -Julia implementation of libsemigroups' `to(kind, kb)` -conversion. It uses the right Cayley graph of the semigroup represented by -`kb` and returns the corresponding trivial congruence. -`kind` selects whether the resulting congruence is one-sided or two-sided. - -# Throws - -- [`LibsemigroupsError`](@ref Semigroups.LibsemigroupsError) if `kb` does not - represent a two-sided congruence or has infinitely many classes. In the - infinite case, use `ToddCoxeter(kind, presentation(kb))` instead. -""" -to(::Type{ToddCoxeter}, kind::congruence_kind, kb::KnuthBendix) = - @wrap_libsemigroups_call LibSemigroups.to_todd_coxeter_from_kb(kind, kb) diff --git a/src/to.jl b/src/to.jl new file mode 100644 index 0000000..ca2c0ea --- /dev/null +++ b/src/to.jl @@ -0,0 +1,229 @@ +# ============================================================================ +# Conversions to Congruence +# ============================================================================ + +""" + to(::Type{Congruence}, kind::congruence_kind, fp::FroidurePin, + wg) -> Congruence + +Convert a Froidure-Pin graph to a Congruence. + +Julia implementation of libsemigroups' `to(kind, fp, wg)` +conversion. `wg` must be either the left or right Cayley graph of `fp`. +The result represents the trivial congruence over the semigroup defined by +`fp`. + +`kind` selects whether the resulting congruence is one-sided or two-sided. + +# Throws + +- [`LibsemigroupsError`](@ref Semigroups.LibsemigroupsError) if `wg` is not + the left or right Cayley graph of `fp`. +""" +to(::Type{Congruence}, kind::congruence_kind, fp::FroidurePin, wg) = + @wrap_libsemigroups_call LibSemigroups.to_congruence_from_fpb(kind, fp.cxx_obj, wg) + +""" + to(::Type{Congruence}, kind::congruence_kind, wg::WordGraph) -> Congruence + +Convert a WordGraph to a Congruence. + +Julia implementation of libsemigroups' `to(kind, wg)` +conversion. The result represents the trivial congruence over `wg`. + +`kind` selects whether the resulting congruence is one-sided or two-sided. + +The graph is added to the constructed congruence as-is; no checks are made +that the resulting Todd-Coxeter or Congruence object is valid. +""" +@cxxdereference to(::Type{Congruence}, kind::congruence_kind, wg::WordGraph) = + @wrap_libsemigroups_call LibSemigroups.to_congruence_from_wg(kind, wg) + +# ============================================================================ +# Conversions to ToddCoxeter +# ============================================================================ + +""" + to(::Type{ToddCoxeter}, kind::congruence_kind, fp::FroidurePin, + wg::WordGraph) -> ToddCoxeter + +Convert a Froidure-Pin graph to a Todd-Coxeter. + +Julia implementation of libsemigroups' `to(kind, fp, wg)` +conversion. `wg` must be either the left or right Cayley graph of `fp`. +The result represents the trivial congruence over the semigroup defined by +`fp`. +`kind` selects whether the resulting congruence is one-sided or two-sided. + +# Throws + +- [`LibsemigroupsError`](@ref Semigroups.LibsemigroupsError) if `wg` is not + the left or right Cayley graph of `fp`. +""" +to(::Type{ToddCoxeter}, kind::congruence_kind, fp::FroidurePin, wg) = + @wrap_libsemigroups_call LibSemigroups.to_todd_coxeter_from_fpb(kind, fp.cxx_obj, wg) + +""" + to(::Type{ToddCoxeter}, kind::congruence_kind, kb::KnuthBendix) -> ToddCoxeter + +Convert a Knuth-Bendix to a Todd-Coxeter. + +Julia implementation of libsemigroups' `to(kind, kb)` +conversion. It uses the right Cayley graph of the semigroup represented by +`kb` and returns the corresponding trivial congruence. +`kind` selects whether the resulting congruence is one-sided or two-sided. + +# Throws + +- [`LibsemigroupsError`](@ref Semigroups.LibsemigroupsError) if `kb` does not + represent a two-sided congruence or has infinitely many classes. In the + infinite case, use `ToddCoxeter(kind, presentation(kb))` instead. +""" +to(::Type{ToddCoxeter}, kind::congruence_kind, kb::KnuthBendix) = + @wrap_libsemigroups_call LibSemigroups.to_todd_coxeter_from_kb(kind, kb) + +# ============================================================================ +# Conversions to Presentation +# ============================================================================ + +""" + to(::Type{Presentation}, p::Presentation) -> Presentation + +Julia implementation of the identity conversion for `Presentation`. The +returned presentation is a copy of `p`. +""" +to(::Type{Presentation}, p::Presentation) = Presentation(p) + +""" + to(::Type{Presentation}, c::Congruence) -> Presentation + +Julia implementation of libsemigroups' `to(c)` conversion. +Return the presentation used to construct or initialise `c`. + +This conversion returns the presentation used to construct or initialise `c`. +Congruence-generating pairs are not added to the returned presentation by +running `c`. +""" +to(::Type{Presentation}, c::Congruence) = LibSemigroups.to_presentation_word(c) + +""" + to(::Type{Presentation}, k::Kambites) -> Presentation + +Julia implementation of libsemigroups' `to(k)` conversion. +Return a presentation equivalent to the presentation used to construct or +initialise `k`. + +This conversion does not enumerate `k`. +""" +to(::Type{Presentation}, k::Kambites) = LibSemigroups.to_presentation_word(k) + +""" + to(::Type{Presentation}, tc::ToddCoxeter) -> Presentation + +Julia implementation of libsemigroups' `to(tc)` conversion. +Return the presentation used to construct or initialise `tc`. + +This conversion does not enumerate `tc`. +""" +to(::Type{Presentation}, tc::ToddCoxeter) = LibSemigroups.to_presentation_word(tc) + +""" + to(::Type{Presentation}, kb::KnuthBendix) -> Presentation + +Julia implementation of libsemigroups' `to(kb)` conversion. +Return a presentation using the currently active rules of `kb`. + +This conversion does not enumerate `kb`, so the returned presentation may not +yet describe the completed semigroup or monoid. Run `kb` first if a fully +processed presentation is required. +""" +to(::Type{Presentation}, kb::KnuthBendix) = LibSemigroups.to_presentation_word(kb) + +""" + to(::Type{Presentation}, fp::FroidurePin) -> Presentation + +Julia implementation of libsemigroups' `to(fp)` conversion. +Return a presentation using the currently known rules of `fp`. + +This conversion enumerates `fp` before obtaining its presentation. +""" +to(::Type{Presentation}, fp::FroidurePin) = LibSemigroups.to_presentation_word(fp.cxx_obj) + +# ============================================================================ +# Conversions to KnuthBendix +# ============================================================================ + +""" + to(::Type{KnuthBendix}, kind::congruence_kind, fp::FroidurePin) -> KnuthBendix + +Julia implementation of libsemigroups' `to(kind, fp)` +conversion. It constructs a Knuth-Bendix instance from the presentation +obtained from `fp` and represents the trivial congruence over that semigroup. +`kind` selects whether the resulting congruence is one-sided or two-sided. + +This conversion enumerates `fp` before obtaining its presentation. +""" +to(::Type{KnuthBendix}, kind::congruence_kind, fp::FroidurePin) = + LibSemigroups.to_knuth_bendix_from_fpb(kind, fp.cxx_obj) + +""" + to(::Type{KnuthBendix}, kind::congruence_kind, tc::ToddCoxeter) -> KnuthBendix + +Julia implementation of libsemigroups' `to(kind, tc)` +conversion. It constructs a Knuth-Bendix instance from `tc.presentation()` +and represents the trivial congruence over the semigroup defined by `tc`. +`kind` selects whether the resulting congruence is one-sided or two-sided. +""" +to(::Type{KnuthBendix}, kind::congruence_kind, tc::ToddCoxeter) = + LibSemigroups.to_knuth_bendix_from_tc(kind, tc) + +# ============================================================================ +# Conversions to FroidurePin +# ============================================================================ + +""" + to(::Type{FroidurePin}, wg::WordGraph) -> FroidurePin{Transf{UInt32}} + +Convert a complete `WordGraph` to a Froidure-Pin whose elements are +`Transf{UInt32}`. This is the Julia implementation of +libsemigroups' `to(wg)` conversion. Each graph label becomes a +transformation generator, with the transformation image determined by the +edge target for each node. + +The graph must be complete, and every target must be a node of the graph. + +# Throws + +- [`LibsemigroupsError`](@ref Semigroups.LibsemigroupsError) if the graph is + incomplete or contains an out-of-range target. +""" +@cxxdereference to(::Type{FroidurePin}, wg::WordGraph) = + FroidurePin{Transf{UInt32}}(@wrap_libsemigroups_call begin + LibSemigroups.to_froidure_pin_from_wg(wg) + end) + +# ============================================================================ +# Conversions to InversePresentation +# ============================================================================ + +""" + to(::Type{InversePresentation}, p::Presentation) -> InversePresentation + +Convert a Presentation to an InversePresentation. + +Julia implementation of libsemigroups' `to(p)` +conversion. The resulting inverse presentation has rules equivalent to +those of `p`, over a normalised alphabet with a corresponding inverse +letter for each letter of `p`. +""" +to(::Type{InversePresentation}, p::Presentation) = + @wrap_libsemigroups_call LibSemigroups.to_inverse_presentation_word(p) + +""" + to(::Type{InversePresentation}, ip::InversePresentation) -> InversePresentation + +Convert an InversePresentation to an InversePresentation. + +Return a copy of `ip`. +""" +to(::Type{InversePresentation}, ip::InversePresentation) = InversePresentation(ip) diff --git a/test/runtests.jl b/test/runtests.jl index 5c99d6d..fa540e1 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -28,10 +28,5 @@ using Semigroups include("test_knuth_bendix_6.jl") include("test_todd_coxeter.jl") include("test_kambites.jl") - include("test_to_todd_coxeter.jl") - include("test_to_presentation.jl") - include("test_to_knuth_bendix.jl") - include("test_to_congruence.jl") - include("test_to_inverse_presentation.jl") - include("test_to_froidure_pin.jl") + include("test_to.jl") end diff --git a/test/test_to.jl b/test/test_to.jl new file mode 100644 index 0000000..dcb1fe1 --- /dev/null +++ b/test/test_to.jl @@ -0,0 +1,354 @@ +using Test +using Semigroups + +@testset verbose = true "to ToddCoxeter" begin + @testset "scaffolding" begin + # Check conversions from Froidure-Pin and Knuth-Bendix. + @test hasmethod( + Semigroups.to, + Tuple{Type{ToddCoxeter},congruence_kind,FroidurePin,Any}, + ) + @test hasmethod(Semigroups.to, Tuple{Type{ToddCoxeter},congruence_kind,KnuthBendix}) + end + + @testset "from FroidurePin" begin + # Convert a completed Froidure-Pin graph. + fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) + tc = Semigroups.to(ToddCoxeter, twosided, fp, right_cayley_graph(fp)) + + @test tc isa ToddCoxeter + @test alphabet(presentation(tc)) == [1, 2] + end + + @testset "errors are translated" begin + fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) + @test_throws LibsemigroupsError Semigroups.to( + ToddCoxeter, + twosided, + fp, + WordGraph(2, 1), + ) + end + + @testset "from KnuthBendix" begin + # Convert a Knuth-Bendix instance built from a presentation. + p = Presentation() + set_alphabet!(p, 1) + add_rule_no_checks!(p, [1, 1], [1]) + kb = KnuthBendix(twosided, p) + + tc = Semigroups.to(ToddCoxeter, twosided, kb) + + @test tc isa ToddCoxeter + @test alphabet(presentation(tc)) == [1] + @test number_of_classes(tc) == 1 + end +end + +@testset verbose = true "to Presentation" begin + @testset "scaffolding" begin + # Check every public conversion to Presentation. + @test isdefined(Semigroups, :to) + @test hasmethod(Semigroups.to, Tuple{Type{Presentation},Presentation}) + @test hasmethod(Semigroups.to, Tuple{Type{Presentation},Congruence}) + @test hasmethod(Semigroups.to, Tuple{Type{Presentation},Kambites}) + @test hasmethod(Semigroups.to, Tuple{Type{Presentation},ToddCoxeter}) + @test hasmethod(Semigroups.to, Tuple{Type{Presentation},KnuthBendix}) + @test hasmethod(Semigroups.to, Tuple{Type{Presentation},FroidurePin}) + end + + @testset "Presentation conversion" begin + # Copying preserves presentation data without aliasing the wrapper. + p = Presentation() + set_alphabet!(p, 2) + add_rule_no_checks!(p, [1, 1], [2]) + set_contains_empty_word!(p, true) + + q = Semigroups.to(Presentation, p) + + @test q isa Presentation + @test q == p + @test q !== p + @test alphabet(q) == alphabet(p) + @test rules(q) == rules(p) + @test contains_empty_word(q) == contains_empty_word(p) + end + + @testset "Congruence conversion" begin + # A congruence converts back to its defining presentation. + p = Presentation() + set_alphabet!(p, 2) + add_rule_no_checks!(p, [1, 1], [2]) + c = Congruence(twosided, p) + + q = Semigroups.to(Presentation, c) + + @test q isa Presentation + @test q == p + end + + @testset "conversion with no rules" begin + # Conversion also preserves an alphabet when there are no rules. + p = Presentation() + set_alphabet!(p, 3) + k = Kambites(twosided, p) + + q = Semigroups.to(Presentation, k) + + @test q isa Presentation + @test q == presentation(k) + @test alphabet(q) == alphabet(p) + @test rules(q) == rules(p) + end + + @testset "conversion of alphabet + rules" begin + # Conversion preserves both alphabet and rules. + p = Presentation() + set_alphabet!(p, 3) + add_rule_no_checks!(p, [1, 2, 1], [2, 3]) + add_rule_no_checks!(p, [3, 3], [1]) + k = Kambites(twosided, p) + + q = Semigroups.to(Presentation, k) + + @test q == presentation(k) + @test q == p + @test alphabet(q) == alphabet(p) + @test rules(q) == rules(p) + end + + @testset "contains empty word" begin + # The empty-word flag is retained by conversion. + p = Presentation() + set_alphabet!(p, 1) + set_contains_empty_word!(p, true) + k = Kambites(twosided, p) + + q = Semigroups.to(Presentation, k) + + @test q == presentation(k) + @test contains_empty_word(q) + end + + @testset "matches Kambites presentation" begin + # The converted presentation matches Kambites exactly. + p = Presentation() + set_alphabet!(p, 2) + add_rule_no_checks!(p, [1, 1], [2]) + k = Kambites(twosided, p) + + q = Semigroups.to(Presentation, k) + + @test q == presentation(k) + @test alphabet(q) == alphabet(presentation(k)) + @test rules(q) == rules(presentation(k)) + end + + @testset "ToddCoxeter conversion" begin + # Conversion preserves the Todd-Coxeter presentation data. + p = Presentation() + set_alphabet!(p, 2) + add_rule_no_checks!(p, [1, 1], [2]) + tc = ToddCoxeter(twosided, p) + + q = Semigroups.to(Presentation, tc) + + @test q isa Presentation + @test q == presentation(tc) + @test alphabet(q) == alphabet(p) + @test rules(q) == rules(p) + end + + @testset "ToddCoxeter conversion contains empty word" begin + # Check the empty-word flag for Todd-Coxeter conversion. + p = Presentation() + set_alphabet!(p, 1) + set_contains_empty_word!(p, true) + tc = ToddCoxeter(twosided, p) + + @test contains_empty_word(Semigroups.to(Presentation, tc)) + end + + @testset "KnuthBendix conversion" begin + # Conversion exposes the active Knuth-Bendix rules. + p = Presentation() + set_alphabet!(p, 2) + add_rule_no_checks!(p, [1, 1], [1]) + kb = KnuthBendix(twosided, p) + run!(kb) + + q = Semigroups.to(Presentation, kb) + + @test q isa Presentation + @test alphabet(q) == alphabet(presentation(kb)) + @test rules(q) == active_rules(kb) + @test number_of_rules(q) == length(active_rules(kb)) + end + + @testset "KnuthBendix conversion contains empty word" begin + # Check the empty-word flag for Knuth-Bendix conversion. + p = Presentation() + set_alphabet!(p, 1) + set_contains_empty_word!(p, true) + kb = KnuthBendix(twosided, p) + + @test contains_empty_word(Semigroups.to(Presentation, kb)) + end + + @testset "FroidurePin conversion" begin + # Conversion produces a valid presentation from Froidure-Pin. + fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) + + @test !finished(fp) + + q = Semigroups.to(Presentation, fp) + + @test finished(fp) + @test q isa Presentation + @test alphabet(q) == [1, 2] + @test number_of_rules(q) > 0 + throw_if_bad_alphabet_or_rules(q) + end +end + +@testset verbose = true "to KnuthBendix" begin + @testset "scaffolding" begin + # Check conversions from Froidure-Pin and Todd-Coxeter. + @test hasmethod(Semigroups.to, Tuple{Type{KnuthBendix},congruence_kind,FroidurePin}) + @test hasmethod(Semigroups.to, Tuple{Type{KnuthBendix},congruence_kind,ToddCoxeter}) + end + + @testset "from FroidurePin" begin + # Conversion from a completed Froidure-Pin creates active rules. + fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) + run!(fp) + kb = Semigroups.to(KnuthBendix, twosided, fp) + + @test kb isa KnuthBendix + @test alphabet(presentation(kb)) == [1, 2] + @test number_of_rules(presentation(kb)) > 0 + throw_if_bad_alphabet_or_rules(presentation(kb)) + end + + @testset "from ToddCoxeter" begin + # Conversion preserves the Todd-Coxeter presentation. + p = Presentation() + set_alphabet!(p, 1) + add_rule_no_checks!(p, [1, 1], [1]) + tc = ToddCoxeter(twosided, p) + + kb = Semigroups.to(KnuthBendix, twosided, tc) + + @test kb isa KnuthBendix + @test presentation(kb) == presentation(tc) + end +end + +@testset verbose = true "to Congruence" begin + @testset "scaffolding" begin + # Check both public conversion signatures. + @test hasmethod( + Semigroups.to, + Tuple{Type{Congruence},congruence_kind,FroidurePin,Any}, + ) + @test hasmethod(Semigroups.to, Tuple{Type{Congruence},congruence_kind,WordGraph}) + end + + @testset "from FroidurePin" begin + # Convert the right Cayley graph of a completed Froidure-Pin. + fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) + run!(fp) + c = Semigroups.to(Congruence, twosided, fp, right_cayley_graph(fp)) + + @test c isa Congruence + @test c isa CongruenceCommon + @test number_of_classes(c) == 6 + @test kind(c) == twosided + @test alphabet(presentation(c)) == [1, 2] + end + + @testset "from WordGraph" begin + # Convert a graph directly without a Froidure-Pin wrapper. + wg = WordGraph(2, 1) + target!(wg, 1, 1, 2) + target!(wg, 2, 1, 2) + + c = Semigroups.to(Congruence, twosided, wg) + + @test c isa Congruence + @test c isa CongruenceCommon + @test number_of_classes(c) == 1 + @test kind(c) == twosided + @test alphabet(presentation(c)) == [1] + end + + @testset "errors are translated" begin + fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) + @test_throws LibsemigroupsError Semigroups.to( + Congruence, + twosided, + fp, + WordGraph(2, 1), + ) + end +end + +@testset verbose = true "to InversePresentation" begin + @testset "scaffolding" begin + # Check conversion from Presentation and copying an inverse presentation. + @test hasmethod(Semigroups.to, Tuple{Type{InversePresentation},Presentation}) + @test hasmethod(Semigroups.to, Tuple{Type{InversePresentation},InversePresentation}) + end + + @testset "from Presentation" begin + # Conversion adds inverse generators and preserves the original rules. + p = Presentation() + set_alphabet!(p, 2) + add_rule_no_checks!(p, [1, 2], [2, 1]) + + ip = Semigroups.to(InversePresentation, p) + + @test ip isa InversePresentation + @test alphabet(ip) == [1, 2, 3, 4] + @test rules(ip) == rules(p) + @test inverses(ip) == [3, 4, 1, 2] + throw_if_bad_alphabet_rules_or_inverses(ip) + end + + @testset "copy" begin + # Copy conversion must produce an equal but distinct wrapper. + p = Presentation() + set_alphabet!(p, 1) + ip = InversePresentation(p) + set_inverses!(ip, [1]) + + copy = Semigroups.to(InversePresentation, ip) + + @test copy isa InversePresentation + @test copy !== ip + @test copy == ip + @test inverses(copy) == [1] + end +end + +@testset verbose = true "to FroidurePin" begin + @testset "scaffolding" begin + @test hasmethod(Semigroups.to, Tuple{Type{FroidurePin},WordGraph}) + end + + @testset "from WordGraph" begin + wg = WordGraph(2, 1) + target!(wg, 1, 1, 2) + target!(wg, 2, 1, 2) + + fp = Semigroups.to(FroidurePin, wg) + + @test fp isa FroidurePin{Transf{UInt32}} + @test number_of_generators(fp) == 1 + @test degree(fp) == 2 + end + + @testset "errors are translated" begin + @test_throws LibsemigroupsError Semigroups.to(FroidurePin, WordGraph(2, 1)) + end +end diff --git a/test/test_to_congruence.jl b/test/test_to_congruence.jl deleted file mode 100644 index 807532d..0000000 --- a/test/test_to_congruence.jl +++ /dev/null @@ -1,51 +0,0 @@ -using Test -using Semigroups - -@testset verbose = true "to Congruence" begin - @testset "scaffolding" begin - # Check both public conversion signatures. - @test hasmethod( - Semigroups.to, - Tuple{Type{Congruence},congruence_kind,FroidurePin,Any}, - ) - @test hasmethod(Semigroups.to, Tuple{Type{Congruence},congruence_kind,WordGraph}) - end - - @testset "from FroidurePin" begin - # Convert the right Cayley graph of a completed Froidure-Pin. - fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) - run!(fp) - c = Semigroups.to(Congruence, twosided, fp, right_cayley_graph(fp)) - - @test c isa Congruence - @test c isa CongruenceCommon - @test number_of_classes(c) == 6 - @test kind(c) == twosided - @test alphabet(presentation(c)) == [1, 2] - end - - @testset "from WordGraph" begin - # Convert a graph directly without a Froidure-Pin wrapper. - wg = WordGraph(2, 1) - target!(wg, 1, 1, 2) - target!(wg, 2, 1, 2) - - c = Semigroups.to(Congruence, twosided, wg) - - @test c isa Congruence - @test c isa CongruenceCommon - @test number_of_classes(c) == 1 - @test kind(c) == twosided - @test alphabet(presentation(c)) == [1] - end - - @testset "errors are translated" begin - fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) - @test_throws LibsemigroupsError Semigroups.to( - Congruence, - twosided, - fp, - WordGraph(2, 1), - ) - end -end diff --git a/test/test_to_froidure_pin.jl b/test/test_to_froidure_pin.jl deleted file mode 100644 index 6458ffb..0000000 --- a/test/test_to_froidure_pin.jl +++ /dev/null @@ -1,24 +0,0 @@ -using Test -using Semigroups - -@testset verbose = true "to FroidurePin" begin - @testset "scaffolding" begin - @test hasmethod(Semigroups.to, Tuple{Type{FroidurePin},WordGraph}) - end - - @testset "from WordGraph" begin - wg = WordGraph(2, 1) - target!(wg, 1, 1, 2) - target!(wg, 2, 1, 2) - - fp = Semigroups.to(FroidurePin, wg) - - @test fp isa FroidurePin{Transf{UInt32}} - @test number_of_generators(fp) == 1 - @test degree(fp) == 2 - end - - @testset "errors are translated" begin - @test_throws LibsemigroupsError Semigroups.to(FroidurePin, WordGraph(2, 1)) - end -end diff --git a/test/test_to_inverse_presentation.jl b/test/test_to_inverse_presentation.jl deleted file mode 100644 index eb65ce2..0000000 --- a/test/test_to_inverse_presentation.jl +++ /dev/null @@ -1,40 +0,0 @@ -using Test -using Semigroups - -@testset verbose = true "to InversePresentation" begin - @testset "scaffolding" begin - # Check conversion from Presentation and copying an inverse presentation. - @test hasmethod(Semigroups.to, Tuple{Type{InversePresentation},Presentation}) - @test hasmethod(Semigroups.to, Tuple{Type{InversePresentation},InversePresentation}) - end - - @testset "from Presentation" begin - # Conversion adds inverse generators and preserves the original rules. - p = Presentation() - set_alphabet!(p, 2) - add_rule_no_checks!(p, [1, 2], [2, 1]) - - ip = Semigroups.to(InversePresentation, p) - - @test ip isa InversePresentation - @test alphabet(ip) == [1, 2, 3, 4] - @test rules(ip) == rules(p) - @test inverses(ip) == [3, 4, 1, 2] - throw_if_bad_alphabet_rules_or_inverses(ip) - end - - @testset "copy" begin - # Copy conversion must produce an equal but distinct wrapper. - p = Presentation() - set_alphabet!(p, 1) - ip = InversePresentation(p) - set_inverses!(ip, [1]) - - copy = Semigroups.to(InversePresentation, ip) - - @test copy isa InversePresentation - @test copy !== ip - @test copy == ip - @test inverses(copy) == [1] - end -end diff --git a/test/test_to_knuth_bendix.jl b/test/test_to_knuth_bendix.jl deleted file mode 100644 index b47beff..0000000 --- a/test/test_to_knuth_bendix.jl +++ /dev/null @@ -1,35 +0,0 @@ -using Test -using Semigroups - -@testset verbose = true "to KnuthBendix" begin - @testset "scaffolding" begin - # Check conversions from Froidure-Pin and Todd-Coxeter. - @test hasmethod(Semigroups.to, Tuple{Type{KnuthBendix},congruence_kind,FroidurePin}) - @test hasmethod(Semigroups.to, Tuple{Type{KnuthBendix},congruence_kind,ToddCoxeter}) - end - - @testset "from FroidurePin" begin - # Conversion from a completed Froidure-Pin creates active rules. - fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) - run!(fp) - kb = Semigroups.to(KnuthBendix, twosided, fp) - - @test kb isa KnuthBendix - @test alphabet(presentation(kb)) == [1, 2] - @test number_of_rules(presentation(kb)) > 0 - throw_if_bad_alphabet_or_rules(presentation(kb)) - end - - @testset "from ToddCoxeter" begin - # Conversion preserves the Todd-Coxeter presentation. - p = Presentation() - set_alphabet!(p, 1) - add_rule_no_checks!(p, [1, 1], [1]) - tc = ToddCoxeter(twosided, p) - - kb = Semigroups.to(KnuthBendix, twosided, tc) - - @test kb isa KnuthBendix - @test presentation(kb) == presentation(tc) - end -end diff --git a/test/test_to_presentation.jl b/test/test_to_presentation.jl deleted file mode 100644 index 9701413..0000000 --- a/test/test_to_presentation.jl +++ /dev/null @@ -1,168 +0,0 @@ -using Test -using Semigroups - -@testset verbose = true "to Presentation" begin - @testset "scaffolding" begin - # Check every public conversion to Presentation. - @test isdefined(Semigroups, :to) - @test hasmethod(Semigroups.to, Tuple{Type{Presentation},Presentation}) - @test hasmethod(Semigroups.to, Tuple{Type{Presentation},Congruence}) - @test hasmethod(Semigroups.to, Tuple{Type{Presentation},Kambites}) - @test hasmethod(Semigroups.to, Tuple{Type{Presentation},ToddCoxeter}) - @test hasmethod(Semigroups.to, Tuple{Type{Presentation},KnuthBendix}) - @test hasmethod(Semigroups.to, Tuple{Type{Presentation},FroidurePin}) - end - - @testset "Presentation conversion" begin - # Copying preserves presentation data without aliasing the wrapper. - p = Presentation() - set_alphabet!(p, 2) - add_rule_no_checks!(p, [1, 1], [2]) - set_contains_empty_word!(p, true) - - q = Semigroups.to(Presentation, p) - - @test q isa Presentation - @test q == p - @test q !== p - @test alphabet(q) == alphabet(p) - @test rules(q) == rules(p) - @test contains_empty_word(q) == contains_empty_word(p) - end - - @testset "Congruence conversion" begin - # A congruence converts back to its defining presentation. - p = Presentation() - set_alphabet!(p, 2) - add_rule_no_checks!(p, [1, 1], [2]) - c = Congruence(twosided, p) - - q = Semigroups.to(Presentation, c) - - @test q isa Presentation - @test q == p - end - - @testset "conversion with no rules" begin - # Conversion also preserves an alphabet when there are no rules. - p = Presentation() - set_alphabet!(p, 3) - k = Kambites(twosided, p) - - q = Semigroups.to(Presentation, k) - - @test q isa Presentation - @test q == presentation(k) - @test alphabet(q) == alphabet(p) - @test rules(q) == rules(p) - end - - @testset "conversion of alphabet + rules" begin - # Conversion preserves both alphabet and rules. - p = Presentation() - set_alphabet!(p, 3) - add_rule_no_checks!(p, [1, 2, 1], [2, 3]) - add_rule_no_checks!(p, [3, 3], [1]) - k = Kambites(twosided, p) - - q = Semigroups.to(Presentation, k) - - @test q == presentation(k) - @test q == p - @test alphabet(q) == alphabet(p) - @test rules(q) == rules(p) - end - - @testset "contains empty word" begin - # The empty-word flag is retained by conversion. - p = Presentation() - set_alphabet!(p, 1) - set_contains_empty_word!(p, true) - k = Kambites(twosided, p) - - q = Semigroups.to(Presentation, k) - - @test q == presentation(k) - @test contains_empty_word(q) - end - - @testset "matches Kambites presentation" begin - # The converted presentation matches Kambites exactly. - p = Presentation() - set_alphabet!(p, 2) - add_rule_no_checks!(p, [1, 1], [2]) - k = Kambites(twosided, p) - - q = Semigroups.to(Presentation, k) - - @test q == presentation(k) - @test alphabet(q) == alphabet(presentation(k)) - @test rules(q) == rules(presentation(k)) - end - - @testset "ToddCoxeter conversion" begin - # Conversion preserves the Todd-Coxeter presentation data. - p = Presentation() - set_alphabet!(p, 2) - add_rule_no_checks!(p, [1, 1], [2]) - tc = ToddCoxeter(twosided, p) - - q = Semigroups.to(Presentation, tc) - - @test q isa Presentation - @test q == presentation(tc) - @test alphabet(q) == alphabet(p) - @test rules(q) == rules(p) - end - - @testset "ToddCoxeter conversion contains empty word" begin - # Check the empty-word flag for Todd-Coxeter conversion. - p = Presentation() - set_alphabet!(p, 1) - set_contains_empty_word!(p, true) - tc = ToddCoxeter(twosided, p) - - @test contains_empty_word(Semigroups.to(Presentation, tc)) - end - - @testset "KnuthBendix conversion" begin - # Conversion exposes the active Knuth-Bendix rules. - p = Presentation() - set_alphabet!(p, 2) - add_rule_no_checks!(p, [1, 1], [1]) - kb = KnuthBendix(twosided, p) - run!(kb) - - q = Semigroups.to(Presentation, kb) - - @test q isa Presentation - @test alphabet(q) == alphabet(presentation(kb)) - @test rules(q) == active_rules(kb) - @test number_of_rules(q) == length(active_rules(kb)) - end - - @testset "KnuthBendix conversion contains empty word" begin - # Check the empty-word flag for Knuth-Bendix conversion. - p = Presentation() - set_alphabet!(p, 1) - set_contains_empty_word!(p, true) - kb = KnuthBendix(twosided, p) - - @test contains_empty_word(Semigroups.to(Presentation, kb)) - end - - @testset "FroidurePin conversion" begin - # Conversion produces a valid presentation from Froidure-Pin. - fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) - - @test !finished(fp) - - q = Semigroups.to(Presentation, fp) - - @test finished(fp) - @test q isa Presentation - @test alphabet(q) == [1, 2] - @test number_of_rules(q) > 0 - throw_if_bad_alphabet_or_rules(q) - end -end diff --git a/test/test_to_todd_coxeter.jl b/test/test_to_todd_coxeter.jl deleted file mode 100644 index 5e2976a..0000000 --- a/test/test_to_todd_coxeter.jl +++ /dev/null @@ -1,46 +0,0 @@ -using Test -using Semigroups - -@testset verbose = true "to ToddCoxeter" begin - @testset "scaffolding" begin - # Check conversions from Froidure-Pin and Knuth-Bendix. - @test hasmethod( - Semigroups.to, - Tuple{Type{ToddCoxeter},congruence_kind,FroidurePin,Any}, - ) - @test hasmethod(Semigroups.to, Tuple{Type{ToddCoxeter},congruence_kind,KnuthBendix}) - end - - @testset "from FroidurePin" begin - # Convert a completed Froidure-Pin graph. - fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) - tc = Semigroups.to(ToddCoxeter, twosided, fp, right_cayley_graph(fp)) - - @test tc isa ToddCoxeter - @test alphabet(presentation(tc)) == [1, 2] - end - - @testset "errors are translated" begin - fp = FroidurePin(Transf([2, 1, 3]), Transf([2, 3, 1])) - @test_throws LibsemigroupsError Semigroups.to( - ToddCoxeter, - twosided, - fp, - WordGraph(2, 1), - ) - end - - @testset "from KnuthBendix" begin - # Convert a Knuth-Bendix instance built from a presentation. - p = Presentation() - set_alphabet!(p, 1) - add_rule_no_checks!(p, [1, 1], [1]) - kb = KnuthBendix(twosided, p) - - tc = Semigroups.to(ToddCoxeter, twosided, kb) - - @test tc isa ToddCoxeter - @test alphabet(presentation(tc)) == [1] - @test number_of_classes(tc) == 1 - end -end