Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
46c1d74
feat: add Runner, RunnerState
jswent Feb 7, 2026
b7b7093
run formatter
jswent Feb 7, 2026
baade42
fix: attempt fmt fix for consteval ubuntu
jswent Feb 7, 2026
44ee3ed
feat: run_until! TimePeriod input, convert implicitly
jswent Feb 7, 2026
55042a2
runner: update dependencies
jswent Feb 7, 2026
f08aa22
runner: add run_until! using @safe_cfunction + fptr
jswent Feb 7, 2026
17f9a3f
runner: fix exports
jswent Feb 7, 2026
8f03fb7
runner: add basic binding tests
jswent Feb 7, 2026
748e827
remove Dates compat, unnecessary
jswent Feb 7, 2026
20b99b2
Merge branch 'main' into add-runner
jswent Feb 7, 2026
5da656c
fix: bad merge import
jswent Feb 7, 2026
71f8b16
fix: non-negative input to run_for!
jswent Feb 7, 2026
d416cd2
fix formatter imports again
jswent Feb 7, 2026
403c76b
add basic read-only WordGraph for FroidurePin
jswent Feb 7, 2026
fc140f0
add some basic tests for WordGraph
jswent Feb 7, 2026
0b8fa73
Merge branch 'add-wordgraph' into add-froidure-pin
jswent Feb 7, 2026
71ab653
add FroidurePinBase bindings
jswent Feb 8, 2026
be30a3a
run formatter
jswent Feb 8, 2026
86639aa
add FroidurePin C++ template instantiations
jswent Feb 8, 2026
bcd27d4
update build for FroidurePin<E>
jswent Feb 8, 2026
c2e8cae
add tests for FroidurePin<E> C++ bindings
jswent Feb 8, 2026
eeee0ea
add FroidurePin julia type defs and constructor
jswent Feb 8, 2026
02f5e38
add FroidurePin runner config
jswent Feb 8, 2026
6fb112c
add FroidurePin position, products, idempotents
jswent Feb 8, 2026
1557faa
froidure-pin: add factorization, words, structure, elements
jswent Feb 8, 2026
556195e
froidure-pin: rules, cayley_graph, mutators
jswent Feb 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
name = "Semigroups"
uuid = "f8a5e1c0-7b2d-4a3e-9c6f-1d2e3f4a5b6c"
authors = ["James Swent"]
version = "0.1.0"
authors = ["James Swent"]

[deps]
CxxWrap = "1f15a43c-97ca-5a2a-ae31-89f07a497df4"
AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d"
CxxWrap = "1f15a43c-97ca-5a2a-ae31-89f07a497df4"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"

[compat]
AbstractAlgebra = "0.43, 0.48"
CxxWrap = "0.17"
julia = "1.9"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]

[compat]
julia = "1.9"
CxxWrap = "0.17"
AbstractAlgebra = "0.43, 0.48"
4 changes: 4 additions & 0 deletions deps/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ message(STATUS "libsemigroups libraries: ${LIBSEMIGROUPS_LIBRARIES}")
add_library(libsemigroups_julia SHARED
libsemigroups_julia.cpp
constants.cpp
runner.cpp
word-graph.cpp
froidure-pin-base.cpp
transf.cpp
froidure-pin.cpp
)

# Include directories
Expand Down
317 changes: 317 additions & 0 deletions deps/src/froidure-pin-base.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,317 @@
//
// Semigroups.jl
// Copyright (C) 2026, James W. Swent
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include "libsemigroups_julia.hpp"

#include <libsemigroups/froidure-pin-base.hpp>

#include <cstddef>
#include <cstdint>
#include <vector>

// Explicit SuperType specialization for CxxWrap upcasting.
// Enables CxxBaseRef<FroidurePinBase> to upcast to Runner when calling
// inherited Runner methods (finished, run!, etc.) on FroidurePinBase instances.
namespace jlcxx {
template <> struct SuperType<libsemigroups::FroidurePinBase> {
typedef libsemigroups::Runner type;
};
} // namespace jlcxx

namespace libsemigroups_julia {

void define_froidure_pin_base(jl::Module & m)
{
using libsemigroups::FroidurePinBase;
using libsemigroups::Runner;
using libsemigroups::word_type;
using libsemigroups::froidure_pin::product_by_reduction;

using FPB = FroidurePinBase;
using WG = FPB::cayley_graph_type;

// Register FroidurePinBase inheriting from Runner
auto type =
m.add_type<FroidurePinBase>("FroidurePinBase", jlcxx::julia_base_type<Runner>());

//////////////////////////////////////////////////////////////////////////
// Settings
//////////////////////////////////////////////////////////////////////////

// batch_size - getter
type.method("batch_size", [](FPB const & self) -> size_t {
return self.batch_size();
});

// set_batch_size! - setter (different name to avoid CxxWrap overload issue)
type.method("set_batch_size!", [](FPB & self, size_t val) -> FPB & {
return self.batch_size(val);
});

//////////////////////////////////////////////////////////////////////////
// Size and enumeration
//////////////////////////////////////////////////////////////////////////

// current_size - number of elements enumerated so far (no enumeration)
type.method("current_size", [](FPB const & self) -> size_t {
return self.current_size();
});

// size - full enumeration, returns total size
type.method("size", [](FPB & self) -> size_t {
return self.size();
});

// degree - degree of elements
type.method("degree", [](FPB const & self) -> size_t {
return self.degree();
});

// enumerate - enumerate up to limit elements
type.method("enumerate", [](FPB & self, size_t limit) {
self.enumerate(limit);
});

//////////////////////////////////////////////////////////////////////////
// Rules
//////////////////////////////////////////////////////////////////////////

// number_of_rules - total (triggers full enumeration)
type.method("number_of_rules", [](FPB & self) -> size_t {
return self.number_of_rules();
});

// current_number_of_rules - so far enumerated (no enumeration)
type.method("current_number_of_rules", [](FPB const & self) -> size_t {
return self.current_number_of_rules();
});

//////////////////////////////////////////////////////////////////////////
// Identity element
//////////////////////////////////////////////////////////////////////////

// contains_one - triggers full enumeration
type.method("contains_one", [](FPB & self) -> bool {
return self.contains_one();
});

// currently_contains_one - no enumeration
type.method("currently_contains_one", [](FPB const & self) -> bool {
return self.currently_contains_one();
});

//////////////////////////////////////////////////////////////////////////
// Position queries
//////////////////////////////////////////////////////////////////////////

// position_of_generator - position of i-th generator
type.method("position_of_generator", [](FPB const & self, uint32_t i) -> uint32_t {
return self.position_of_generator(i);
});

//////////////////////////////////////////////////////////////////////////
// Prefix / suffix / first / final letter
//////////////////////////////////////////////////////////////////////////

type.method("prefix", [](FPB const & self, uint32_t pos) -> uint32_t {
return self.prefix(pos);
});

type.method("suffix", [](FPB const & self, uint32_t pos) -> uint32_t {
return self.suffix(pos);
});

type.method("first_letter", [](FPB const & self, uint32_t pos) -> uint32_t {
return self.first_letter(pos);
});

type.method("final_letter", [](FPB const & self, uint32_t pos) -> uint32_t {
return self.final_letter(pos);
});

//////////////////////////////////////////////////////////////////////////
// Word lengths
//////////////////////////////////////////////////////////////////////////

// current_length - no enumeration
type.method("current_length", [](FPB const & self, uint32_t pos) -> size_t {
return self.current_length(pos);
});

// length - triggers enumeration
type.method("length", [](FPB & self, uint32_t pos) -> size_t {
return self.length(pos);
});

// current_max_word_length - no enumeration
type.method("current_max_word_length", [](FPB const & self) -> size_t {
return self.current_max_word_length();
});

//////////////////////////////////////////////////////////////////////////
// Number of elements by length
//////////////////////////////////////////////////////////////////////////

// number_of_elements_of_length - single length (no enumeration)
type.method("number_of_elements_of_length", [](FPB const & self, size_t len) -> size_t {
return self.number_of_elements_of_length(len);
});

// number_of_elements_of_length_range - range [min, max) (no enumeration)
type.method("number_of_elements_of_length_range",
[](FPB const & self, size_t min, size_t max) -> size_t {
return self.number_of_elements_of_length(min, max);
});

//////////////////////////////////////////////////////////////////////////
// Cayley graphs (return by copy for safety)
//////////////////////////////////////////////////////////////////////////

// right_cayley_graph - triggers full enumeration
type.method("right_cayley_graph", [](FPB & self) -> WG {
return self.right_cayley_graph();
});

// left_cayley_graph - triggers full enumeration
type.method("left_cayley_graph", [](FPB & self) -> WG {
return self.left_cayley_graph();
});

// current_right_cayley_graph - no enumeration
type.method("current_right_cayley_graph", [](FPB const & self) -> WG {
return self.current_right_cayley_graph();
});

// current_left_cayley_graph - no enumeration
type.method("current_left_cayley_graph", [](FPB const & self) -> WG {
return self.current_left_cayley_graph();
});

//////////////////////////////////////////////////////////////////////////
// Free functions: product_by_reduction
//////////////////////////////////////////////////////////////////////////

m.method("product_by_reduction",
[](FPB const & fpb, uint32_t i, uint32_t j) -> uint32_t {
return product_by_reduction(fpb, i, j);
});

//////////////////////////////////////////////////////////////////////////
// Free functions: factorisation
//////////////////////////////////////////////////////////////////////////

// current_minimal_factorisation - no enumeration, returns word_type
m.method("current_minimal_factorisation",
[](FPB const & fpb, uint32_t pos) -> word_type {
return libsemigroups::froidure_pin::current_minimal_factorisation(fpb, pos);
});

// minimal_factorisation - triggers enumeration, returns word_type
m.method("minimal_factorisation", [](FPB & fpb, uint32_t pos) -> word_type {
return libsemigroups::froidure_pin::minimal_factorisation(fpb, pos);
});

// factorisation - triggers enumeration, returns word_type
m.method("factorisation", [](FPB & fpb, uint32_t pos) -> word_type {
return libsemigroups::froidure_pin::factorisation(fpb, pos);
});

//////////////////////////////////////////////////////////////////////////
// Free functions: position from word
//////////////////////////////////////////////////////////////////////////

// current_position_word - no enumeration, returns UNDEFINED if not found
m.method("current_position_word",
[](FPB const & fpb, std::vector<size_t> const & w) -> uint32_t {
return libsemigroups::froidure_pin::current_position(fpb, w);
});

// position_word - triggers full enumeration
m.method("position_word", [](FPB & fpb, std::vector<size_t> const & w) -> uint32_t {
return libsemigroups::froidure_pin::position(fpb, w);
});

//////////////////////////////////////////////////////////////////////////
// Free functions: rules (two parallel vectors)
//////////////////////////////////////////////////////////////////////////

// rules_lhs_vector - full enumeration, returns LHS of all rules
m.method("rules_lhs_vector", [](FPB & fpb) -> std::vector<word_type> {
std::vector<word_type> result;
for (auto const & [lhs, rhs] : libsemigroups::froidure_pin::rules(fpb))
{
result.push_back(lhs);
}
return result;
});

// rules_rhs_vector - full enumeration, returns RHS of all rules
m.method("rules_rhs_vector", [](FPB & fpb) -> std::vector<word_type> {
std::vector<word_type> result;
for (auto const & [lhs, rhs] : libsemigroups::froidure_pin::rules(fpb))
{
result.push_back(rhs);
}
return result;
});

// current_rules_lhs_vector - no enumeration
m.method("current_rules_lhs_vector", [](FPB const & fpb) -> std::vector<word_type> {
std::vector<word_type> result;
for (auto const & [lhs, rhs] : libsemigroups::froidure_pin::current_rules(fpb))
{
result.push_back(lhs);
}
return result;
});

// current_rules_rhs_vector - no enumeration
m.method("current_rules_rhs_vector", [](FPB const & fpb) -> std::vector<word_type> {
std::vector<word_type> result;
for (auto const & [lhs, rhs] : libsemigroups::froidure_pin::current_rules(fpb))
{
result.push_back(rhs);
}
return result;
});

//////////////////////////////////////////////////////////////////////////
// Free functions: normal forms
//////////////////////////////////////////////////////////////////////////

// normal_forms_vector - full enumeration
m.method("normal_forms_vector", [](FPB & fpb) -> std::vector<word_type> {
std::vector<word_type> result;
for (auto const & w : libsemigroups::froidure_pin::normal_forms(fpb))
{
result.push_back(w);
}
return result;
});

// current_normal_forms_vector - no enumeration
m.method("current_normal_forms_vector", [](FPB const & fpb) -> std::vector<word_type> {
std::vector<word_type> result;
for (auto const & w : libsemigroups::froidure_pin::current_normal_forms(fpb))
{
result.push_back(w);
}
return result;
});
}

} // namespace libsemigroups_julia
Loading
Loading