Skip to content

Commit

Permalink
More docs - all functions have doc
Browse files Browse the repository at this point in the history
  • Loading branch information
Joseph-Edwards committed Jun 7, 2024
1 parent 5e9c22a commit 62158a1
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 27 deletions.
1 change: 1 addition & 0 deletions docs/DoxygenLayout.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<tab type="user" visible="yes" url="@ref paths_group" title="Paths"/>
<tab type="usergroup" visible="yes" url="@ref presentations_group" title="Presentations">
<tab type="user" visible="yes" url="@ref libsemigroups::Presentation" title="Presentation class" />
<tab type="user" visible="yes" url="@ref libsemigroups::InversePresentation" title="InversePresentation class" />
<tab type="usergroup" visible="yes" url="@ref libsemigroups::presentation" title="Helper functions" />
<tab type="usergroup" visible="yes" url="@ref libsemigroups::fpsemigroup" title="Examples" />
</tab>
Expand Down
239 changes: 213 additions & 26 deletions include/libsemigroups/presentation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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 <typename Word>
void add_cyclic_conjugates(Presentation<Word>& p,
Word const& lhs,
Expand Down Expand Up @@ -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<Word>
//! Presentation<Word>.
//!
//! \tparam Word the type of the underlying words.
template <typename Word>
class InversePresentation : public Presentation<Word> {
public:
using word_type = typename Presentation<Word>::word_type;
using letter_type = typename Presentation<Word>::letter_type;
//! \brief The type of the words in the rules of an InversePresentation
//! object.
using word_type = typename Presentation<Word>::word_type;

//! \brief The type of the letters in the words that constitute the rules of
//! an InversePresentation object.
using letter_type = typename Presentation<Word>::letter_type;

//! \brief Type of a const iterator to either side of a rule.
using const_iterator = typename Presentation<Word>::const_iterator;
using iterator = typename Presentation<Word>::iterator;
using size_type = typename Presentation<Word>::size_type;

//! \brief Type of an iterator to either side of a rule.
using iterator = typename Presentation<Word>::iterator;

//! \brief Size type for rules.
using size_type = typename Presentation<Word>::size_type;

private:
word_type _inverses;
Expand All @@ -1990,69 +2002,224 @@ namespace libsemigroups {
using Presentation<Word>::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<Word>(Presentation<Word> const& p)
: Presentation<Word>(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<Word>(Presentation<Word>&& p)
: Presentation<Word>(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<Word>::validate and \ref
//! presentation::validate_semigroup_inverses.
void validate() const {
Presentation<Word>::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 <typename Word>
bool operator==(Presentation<Word> const& lhop,
Presentation<Word> const& rhop) {
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 <typename Word>
bool operator!=(Presentation<Word> const& lhop,
Presentation<Word> 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<std::string> 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<std::string> const& p,
std::string const& input);
[[nodiscard]] word_type to_word(Presentation<std::string> 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<std::string> 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<std::string> const& p, word_type const& w);
std::string to_string(Presentation<std::string> const& p,
word_type const& input);

namespace detail {
template <typename T>
Expand All @@ -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 <typename T>
static constexpr bool IsInversePresentation
= detail::IsInversePresentationHelper<T>::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 <typename T>
static constexpr bool IsPresentation = detail::IsPresentationHelper<T>::value;

Expand Down
18 changes: 18 additions & 0 deletions include/libsemigroups/presentation.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -1036,4 +1036,22 @@ namespace libsemigroups {
}

} // namespace presentation

template <typename Word>
InversePresentation<Word>&
InversePresentation<Word>::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 Word>
typename InversePresentation<Word>::letter_type
InversePresentation<Word>::inverse(letter_type x) const {
if (_inverses.empty()) {
LIBSEMIGROUPS_EXCEPTION("no inverses have been defined")
}
return _inverses[this->index(x)];
}
} // namespace libsemigroups
3 changes: 2 additions & 1 deletion src/presentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ namespace libsemigroups {
});
}

word_type to_word(Presentation<std::string> const& p, std::string const& s) {
[[nodiscard]] word_type to_word(Presentation<std::string> const& p,
std::string const& s) {
word_type w;
to_word(p, s, w);
return w;
Expand Down

0 comments on commit 62158a1

Please sign in to comment.