diff --git a/docs/DoxygenLayout.xml b/docs/DoxygenLayout.xml index 5fb736fd3..ecbfe6333 100644 --- a/docs/DoxygenLayout.xml +++ b/docs/DoxygenLayout.xml @@ -19,6 +19,7 @@ + diff --git a/include/libsemigroups/presentation.hpp b/include/libsemigroups/presentation.hpp index bd64f5eb7..63c70cb18 100644 --- a/include/libsemigroups/presentation.hpp +++ b/include/libsemigroups/presentation.hpp @@ -64,9 +64,10 @@ namespace libsemigroups { //! This file contains documentation related to semigroup and monoid //! presentations in `libsemigroups`. //! - //! There is one class and two namespaces with functionality related to + //! There are two classes and two namespaces with functionality related to //! presentations: //! * \ref Presentation "the Presentation class" + //! * \ref InversePresentation "the InversePresentation class" //! * \ref libsemigroups::presentation "Helper functions for presentations" //! * \ref libsemigroups::fpsemigroup "Presentations for standard examples" @@ -1929,7 +1930,7 @@ namespace libsemigroups { //! //! \throws LibsemigroupsException if either \p lhs or \p rhs contain //! letters not in `p.alphabet()` - // TODO do a proper version of this + // TODO(later) do a proper version of this template void add_cyclic_conjugates(Presentation& p, Word const& lhs, @@ -1971,17 +1972,28 @@ namespace libsemigroups { //! This class template can be used to construction inverse presentations for //! semigroups or monoids and is intended to be used as the input to other //! algorithms in `libsemigroups`. This class inherits from \ref - //! Presentation + //! Presentation. //! //! \tparam Word the type of the underlying words. template class InversePresentation : public Presentation { public: - using word_type = typename Presentation::word_type; - using letter_type = typename Presentation::letter_type; + //! \brief The type of the words in the rules of an InversePresentation + //! object. + using word_type = typename Presentation::word_type; + + //! \brief The type of the letters in the words that constitute the rules of + //! an InversePresentation object. + using letter_type = typename Presentation::letter_type; + + //! \brief Type of a const iterator to either side of a rule. using const_iterator = typename Presentation::const_iterator; - using iterator = typename Presentation::iterator; - using size_type = typename Presentation::size_type; + + //! \brief Type of an iterator to either side of a rule. + using iterator = typename Presentation::iterator; + + //! \brief Size type for rules. + using size_type = typename Presentation::size_type; private: word_type _inverses; @@ -1990,40 +2002,110 @@ namespace libsemigroups { using Presentation::Presentation; // TODO init functions + + //! \brief Construct an InversePresentation from a Presentation reference + //! + //! Construct an InversePresentation, initially with empty inverses, from a + //! reference to a Presentation. + //! + //! \tparam Word the type of the words in the presentation. + //! \param p a reference to the Presentation to construct from. InversePresentation(Presentation const& p) : Presentation(p), _inverses() {} + //! \brief Construct an InversePresentation from a Presentation rvalue + //! reference. + //! + //! Construct an InversePresentation, initially with empty inverses, from a + //! Presentation rvalue reference + //! + //! \tparam Word the type of the words in the presentation. + //! \param p an rvalue reference to the Presentation to construct from. InversePresentation(Presentation&& p) : Presentation(p), _inverses() {} - // TODO validate that checks that inverses are set - // TODO to tpp - InversePresentation& inverses(word_type const& w) { - // TODO maybe don't validate here but only in the validate function to - // be written. Set the alphabet to include the inverses - _inverses = w; - return *this; - } + //! \brief Set the inverse of each letter in the alphabet. + //! + //! Set the inverse of each letter in the alphabet. + //! + //! \param w a word containing the inverses + //! + //! \returns a reference to `this`. + //! + //! \exceptions + //! \no_libsemigroups_except + //! + //! \warning + //! This function does no checks on its argument. In particular, it does not + //! check that the letters in \p w belong to the alphabet, nor does it add + //! new letters to the alphabet. + // TODO(later) validate that checks that inverses are set + InversePresentation& inverses_no_checks(word_type const& w); + //! \brief Return the inverse of each letter in the alphabet. + //! + //! Return the inverse of each letter in the alphabet. + //! + //! \returns a value of type \ref word_type. + //! + //! \exceptions + //! \noexcept word_type const& inverses() const noexcept { return _inverses; } - // TODO to tpp - letter_type inverse(letter_type x) const { - if (_inverses.empty()) { - LIBSEMIGROUPS_EXCEPTION("no inverses have been defined") - } - return _inverses[this->index(x)]; - } + //! \brief Return the inverse of a letter in the alphabet. + //! + //! Return the inverse of the letter \p x. + //! + //! \param x the letter whose index is sought. + //! + //! \returns a value of type \ref letter_type + //! + //! \throws LibsemigroupsException if no inverses have been set, or if + //! `index(letter_type x) const` throws. + letter_type inverse(letter_type x) const; + //! \brief Check if the InversePresentation is valid. + //! + //! Check if the InversePresentation is valid. Specifically, check that the + //! alphabet does not contain duplicate letters, that all rules only contain + //! letters defined in the alphabet, and that the inverses act as semigroup + //! inverses. + //! + //! \throw LibsemigroupsException if: + //! * the alphabet contains duplicate letters + //! * the rules contain letters not defined in the alphabet + //! * the inverses do not act as semigroup inverses + //! + //! \sa + //! \ref Presentation::validate and \ref + //! presentation::validate_semigroup_inverses. void validate() const { Presentation::validate(); presentation::validate_semigroup_inverses(*this, inverses()); } }; - // TODO(doc) + //! \ingroup presentations_group + //! + //! \brief Compare for equality. + //! + //! Returns \c true if \p lhop equals \p rhop by comparing the + //! the alphabets and the rules. + //! + //! \tparam Word the type of the words in the presentations. + //! \param lhop a presentation that is to be compared. + //! \param rhop a presentation that is to be compared. + //! + //! \returns + //! A value of type \c bool. + //! + //! \exceptions + //! \no_libsemigroups_except + //! + //! \complexity + //! At worst linear in the sum of the alphabet sizes and numbers of rules. // TODO(later) also we could do a more sophisticated version of this template bool operator==(Presentation const& lhop, @@ -2031,28 +2113,113 @@ namespace libsemigroups { return lhop.alphabet() == rhop.alphabet() && lhop.rules == rhop.rules; } + //! \ingroup presentations_group + //! + //! \brief Compare for inequality. + //! + //! Returns \c true if \p lhop does not equal \p rhop by comparing the + //! the alphabets and the rules. + //! + //! \tparam Word the type of the words in the presentations. + //! \param lhop a presentation that is to be compared. + //! \param rhop a presentation that is to be compared. + //! + //! \returns + //! A value of type \c bool. + //! + //! \exceptions + //! \no_libsemigroups_except + //! + //! \complexity + //! At worst linear in the sum of the alphabet sizes and numbers of rules. template bool operator!=(Presentation const& lhop, Presentation const& rhop) { return !(lhop == rhop); } + //! \ingroup presentations_group + //! \brief Convert a string to a word_type. + //! + //! This function converts its second argument \p input into a \ref word_type + //! and stores the result in the third argument \p output. The characters of + //! \p input are converted using `p.index()`, so that each letter + //! is mapped to the corresponding index in `p.alphabet()`. + //! + //! The content of the third argument \p output, if any, is removed. + //! + //! \param p the presentation whose alphabet will be used to convert + //! \param input the string to convert + //! \param output word to hold the result + //! + //! \throws LibsemigroupsException if any letter in \p input is not contained + //! in `p.alphabet()`. + //! + //! \sa \ref Presentation::index. // TODO(later) could do a no_check version void to_word(Presentation const& p, std::string const& input, word_type& output); + //! \ingroup presentations_group + //! \brief Convert a string to a word_type. + //! + //! This function converts its second argument \p input into a \ref word_type + //! and returns this result. The characters of \p input are converted using + //! `p.index()`, so that each letter is mapped to the corresponding index in + //! `p.alphabet()`. + //! + //! \param p the presentation whose alphabet will be used to convert + //! \param input the string to convert + //! + //! \throws LibsemigroupsException if any letter in \p input is not contained + //! in `p.alphabet()`. + //! + //! \sa \ref Presentation::index. // TODO(later) could do a no_check version - word_type to_word(Presentation const& p, - std::string const& input); + [[nodiscard]] word_type to_word(Presentation const& p, + std::string const& input); + //! \ingroup presentations_group + //! \brief Convert a word_type to a string. + //! + //! This function converts its second argument \p input into a `string` + //! and stores the result in the third argument \p output. The indices in + //! \p input are converted using `p.letter()`, so that each index + //! is mapped to the corresponding letter. + //! + //! The content of the third argument \p output, if any, is removed. + //! + //! \param p the presentation whose alphabet will be used to convert. + //! \param input the \ref word_type to convert. + //! \param output the `string` to hold the result. + //! + //! \throws LibsemigroupsException if any index in \p input is not in the + //! range `[0, p.alphabet().size())` + //! + //! \sa \ref Presentation::letter. // TODO(later) could do a no_check version void to_string(Presentation const& p, word_type const& input, std::string& output); + //! \ingroup presentations_group + //! \brief Convert a word_type to a string. + //! + //! This function converts its second argument \p input into a `string` + //! and returns this result. The indices in \p input are converted using + //! `p.letter()`, so that each index is mapped to the corresponding letter. + //! + //! \param p the presentation whose alphabet will be used to convert. + //! \param input the \ref word_type to convert. + //! + //! \throws LibsemigroupsException if any index in \p input is not in the + //! range `[0, p.alphabet().size())` + //! + //! \sa \ref Presentation::letter. // TODO(later) could do a no check version - std::string to_string(Presentation const& p, word_type const& w); + std::string to_string(Presentation const& p, + word_type const& input); namespace detail { template @@ -2072,10 +2239,30 @@ namespace libsemigroups { : std::true_type {}; } // namespace detail + //! \ingroup presentations_group + //! + //! \brief Helper variable template. + //! + //! Helper variable template. + //! + //! The value of this variable is \c true if the template parameter \p T is + //! \ref InversePresentation. + //! + //! \tparam T a type. template static constexpr bool IsInversePresentation = detail::IsInversePresentationHelper::value; + //! \ingroup presentations_group + //! + //! \brief Helper variable template. + //! + //! Helper variable template. + //! + //! The value of this variable is \c true if the template parameter \p T is + //! \ref InversePresentation. + //! + //! \tparam T a type. template static constexpr bool IsPresentation = detail::IsPresentationHelper::value; diff --git a/include/libsemigroups/presentation.tpp b/include/libsemigroups/presentation.tpp index ebee26598..d881adca0 100644 --- a/include/libsemigroups/presentation.tpp +++ b/include/libsemigroups/presentation.tpp @@ -1036,4 +1036,22 @@ namespace libsemigroups { } } // namespace presentation + + template + InversePresentation& + InversePresentation::inverses_no_checks(word_type const& w) { + // TODO(later) maybe don't validate here but only in the validate function + // to be written. Set the alphabet to include the inverses + _inverses = w; + return *this; + } + + template + typename InversePresentation::letter_type + InversePresentation::inverse(letter_type x) const { + if (_inverses.empty()) { + LIBSEMIGROUPS_EXCEPTION("no inverses have been defined") + } + return _inverses[this->index(x)]; + } } // namespace libsemigroups diff --git a/src/presentation.cpp b/src/presentation.cpp index 40743bb11..ebdce8bc6 100644 --- a/src/presentation.cpp +++ b/src/presentation.cpp @@ -133,7 +133,8 @@ namespace libsemigroups { }); } - word_type to_word(Presentation const& p, std::string const& s) { + [[nodiscard]] word_type to_word(Presentation const& p, + std::string const& s) { word_type w; to_word(p, s, w); return w;