diff --git a/tc/CMakeLists.txt b/tc/CMakeLists.txt index 2ffa85a..ee13ab0 100644 --- a/tc/CMakeLists.txt +++ b/tc/CMakeLists.txt @@ -1,8 +1,11 @@ add_library(tc - include/tc/groups.hpp - src/groups.cpp include/tc/core.hpp + include/tc/cosets.hpp + include/tc/group.hpp + include/tc/groups.hpp + include/tc/util.hpp src/core.cpp + src/groups.cpp src/solve.cpp) target_include_directories(tc PUBLIC include) diff --git a/tc/include/tc/core.hpp b/tc/include/tc/core.hpp index 81cb556..4bc516b 100644 --- a/tc/include/tc/core.hpp +++ b/tc/include/tc/core.hpp @@ -5,161 +5,6 @@ #include #include -namespace tc { - struct Action { - int from_idx = -1; - int gen = -1; - - Action() = default; - - Action(const Action &) = default; - - Action(int from_idx, int gen); - }; - - struct Path { - std::vector path; - - Path() = default; - - Path(const Path &) = default; - - void add_row(); - - [[nodiscard]] Action get(int to_idx) const; - - void put(int from_idx, int gen, int to_idx); - - template - void walk( - C& res, - T start, - std::vector gens, - std::function op - ) const { - size_t s = size(); - res.reserve(s); - res.push_back(start); - - for (int i = 1; i < s; ++i) { - auto &action = path[i]; - auto &from = res.get(action.from_idx); - auto &val = gens[action.gen]; - res.push_back(op(from,val)); - } - } - - template - [[nodiscard]] std::vector walk( - T start, - std::vector gens, - std::function op - ) const { - std::vector res; - res.reserve(size()); - res.push_back(start); - - for (int i = 1; i < size(); ++i) { - auto &action = path[i]; - auto &from = res[action.from_idx]; - auto &val = gens[action.gen]; - res.push_back(op(from, val)); - } - - return res; - } - - template - [[nodiscard]] std::vector walk( - T start, - std::function op - ) const { - std::vector res; - res.reserve(size()); - res.push_back(start); - - for (int i = 1; i < size(); ++i) { - auto &action = path[i]; - auto &from = res[action.from_idx]; - auto &val = action.gen; - res[i] = op(from, val); - } - - return res; - } - - [[nodiscard]] size_t size() const; - }; - - struct Cosets { - int ngens; - std::vector data; - Path path; - - Cosets(const Cosets &) = default; - - explicit Cosets(int ngens); - - void add_row(); - - void put(int coset, int gen, int target); - - void put(int idx, int target); - - [[nodiscard]] int get(int coset, int gen) const; - - [[nodiscard]] int get(int idx) const; - - [[nodiscard]] size_t size() const; - }; - - struct Rel { - std::array gens; - int mult; - - Rel() = default; - - Rel(const Rel &) = default; - - Rel(int a, int b, int m); - - [[nodiscard]] Rel shift(int off) const; - }; - - struct SubGroup; - - struct Group { - int ngens; - std::vector> _mults; - std::string name; - - Group(const Group &) = default; - - explicit Group(int ngens, const std::vector &rels = {}, std::string name = "G"); - - void set(const Rel &r); - - [[nodiscard]] int get(int a, int b) const; - - [[nodiscard]] std::vector rels() const; - - [[nodiscard]] SubGroup subgroup(const std::vector &gens) const; - - [[nodiscard]] Group product(const Group &other) const; - - [[nodiscard]] Group power(int p) const; - - [[nodiscard]] Cosets solve(const std::vector &sub_gens = {}) const; - }; - - struct SubGroup : public Group { - std::vector gen_map; - const Group &parent; - - SubGroup(const Group &parent, std::vector gen_map); - }; - - Group operator*(const Group &g, const Group &h); - - Group operator^(const Group &g, int p); -} +#include "util.hpp" +#include "cosets.hpp" +#include "group.hpp" diff --git a/tc/include/tc/cosets.hpp b/tc/include/tc/cosets.hpp new file mode 100644 index 0000000..aa8d696 --- /dev/null +++ b/tc/include/tc/cosets.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "cosets.hpp" + +namespace tc { + struct Cosets { + int ngens; + std::vector data; + Path path; + + Cosets(const Cosets &) = default; + + explicit Cosets(int ngens) + : ngens(ngens) { + } + + void add_row() { + data.resize(data.size() + ngens, -1); + path.add_row(); + } + + void put(int coset, int gen, int target) { + data[coset * ngens + gen] = target; + data[target * ngens + gen] = coset; + + if (path.get(target).from_idx == -1) { + path.put(coset, gen, target); + } + } + + void put(int idx, int target) { + int coset = idx / ngens; + int gen = idx % ngens; + data[idx] = target; + data[target * ngens + gen] = coset; + + if (path.get(target).from_idx == -1) { + path.put(coset, gen, target); + } + } + + [[nodiscard]] int get(int coset, int gen) const { + return data[coset * ngens + gen]; + } + + [[nodiscard]] int get(int idx) const { + return data[idx]; + } + + [[nodiscard]] size_t size() const { + return path.size(); + } + }; +} \ No newline at end of file diff --git a/tc/include/tc/group.hpp b/tc/include/tc/group.hpp new file mode 100644 index 0000000..82f9410 --- /dev/null +++ b/tc/include/tc/group.hpp @@ -0,0 +1,98 @@ +#pragma once + +#include + +namespace tc { + struct Group; + struct SubGroup; + + struct Group { + int ngens; + std::vector> _mults; + std::string name; + + Group(const Group &) = default; + + explicit Group(int ngens, const std::vector &rels = {}, std::string name = "G") + : ngens(ngens), name(std::move(name)) { + _mults.resize(ngens); + + for (auto &mult: _mults) { + mult.resize(ngens, 2); + } + + for (const auto &rel: rels) { + set(rel); + } + } + + void set(const Rel &r) { + _mults[r.gens[0]][r.gens[1]] = r.mult; + _mults[r.gens[1]][r.gens[0]] = r.mult; + } + + [[nodiscard]] int get(int a, int b) const { + return _mults[a][b]; + } + + [[nodiscard]] std::vector rels() const { + std::vector res; + for (int i = 0; i < ngens - 1; ++i) { + for (int j = i + 1; j < ngens; ++j) { + res.emplace_back(i, j, get(i, j)); + } + } + return res; + } + + [[nodiscard]] SubGroup subgroup(const std::vector &gens) const; + + [[nodiscard]] Group product(const Group &other) const { + std::stringstream ss; + ss << name << "*" << other.name; + + Group g(ngens + other.ngens, rels(), ss.str()); + + for (const auto &rel: other.rels()) { + g.set(rel.shift(ngens)); + } + + return g; + } + + [[nodiscard]] Group power(int p) const { + std::stringstream ss; + ss << name << "^" << p; + + Group g(ngens * p, {}, ss.str()); + for (const auto &rel: rels()) { + for (int off = 0; off < g.ngens; off += ngens) { + g.set(rel.shift(off)); + } + } + + return g; + } + + [[nodiscard]] Cosets solve(const std::vector &sub_gens = {}) const; + }; + + struct SubGroup : public Group { + std::vector gen_map; + const Group &parent; + + SubGroup(const Group &parent, std::vector gen_map) + : Group(gen_map.size()), parent(parent), gen_map() { + + std::sort(gen_map.begin(), gen_map.end()); + this->gen_map = gen_map; + + for (size_t i = 0; i < gen_map.size(); ++i) { + for (size_t j = 0; j < gen_map.size(); ++j) { + int mult = parent.get(gen_map[i], gen_map[j]); + set(Rel(i, j, mult)); + } + } + } + }; +} diff --git a/tc/include/tc/util.hpp b/tc/include/tc/util.hpp new file mode 100644 index 0000000..9a0c291 --- /dev/null +++ b/tc/include/tc/util.hpp @@ -0,0 +1,120 @@ +#pragma once + +#include +#include +#include +#include + +namespace tc { + struct Action { + int from_idx = -1; + int gen = -1; + + Action() = default; + + Action(const Action &) = default; + + Action(int from_idx, int gen) + : from_idx(from_idx), gen(gen) { + } + }; + + struct Path { + std::vector path; + + Path() = default; + + Path(const Path &) = default; + + void add_row() { + path.resize(path.size() + 1); + } + + [[nodiscard]] Action get(int to_idx) const { + return path[to_idx]; + } + + void put(int from_idx, int gen, int to_idx) { + path[to_idx] = Action(from_idx, gen); + } + + template + void walk( + C &res, + T start, + std::vector gens, + std::function op + ) const { + size_t s = size(); + res.reserve(s); + res.push_back(start); + + for (int i = 1; i < s; ++i) { + auto &action = path[i]; + auto &from = res.get(action.from_idx); + auto &val = gens[action.gen]; + res.push_back(op(from, val)); + } + } + + template + [[nodiscard]] std::vector walk( + T start, + std::vector gens, + std::function op + ) const { + std::vector res; + res.reserve(size()); + res.push_back(start); + + for (int i = 1; i < size(); ++i) { + auto &action = path[i]; + auto &from = res[action.from_idx]; + auto &val = gens[action.gen]; + res.push_back(op(from, val)); + } + + return res; + } + + template + [[nodiscard]] std::vector walk( + T start, + std::function op + ) const { + std::vector res; + res.reserve(size()); + res.push_back(start); + + for (int i = 1; i < size(); ++i) { + auto &action = path[i]; + auto &from = res[action.from_idx]; + auto &val = action.gen; + res[i] = op(from, val); + } + + return res; + } + + [[nodiscard]] size_t size() const { + return path.size(); + } + }; + + struct Rel { + std::array gens; + int mult; + + Rel() = default; + + Rel(const Rel &) = default; + + Rel(int a, int b, int m) + : gens({a, b}), mult(m) { + } + + [[nodiscard]] Rel shift(int off) const { + return Rel(gens[0] + off, gens[1] + off, mult); + } + }; +} diff --git a/tc/src/core.cpp b/tc/src/core.cpp index 09ff19d..1f71b90 100644 --- a/tc/src/core.cpp +++ b/tc/src/core.cpp @@ -1,161 +1,7 @@ -#include "tc/core.hpp" - -#include -#include -#include +#include namespace tc { - Action::Action(int from_idx, int gen) - : from_idx(from_idx), gen(gen) { - } - - void Path::add_row() { - path.resize(path.size() + 1); - } - - Action Path::get(int to_idx) const { - return path[to_idx]; - } - - void Path::put(int from_idx, int gen, int to_idx) { - path[to_idx] = Action(from_idx, gen); - } - - size_t Path::size() const { - return path.size(); - } - - Cosets::Cosets(int ngens) - : ngens(ngens) { - } - - void Cosets::add_row() { - data.resize(data.size() + ngens, -1); - path.add_row(); - } - - void Cosets::put(int coset, int gen, int target) { - data[coset * ngens + gen] = target; - data[target * ngens + gen] = coset; - - if (path.get(target).from_idx == -1) { - path.put(coset, gen, target); - } - } - - void Cosets::put(int idx, int target) { - int coset = idx / ngens; - int gen = idx % ngens; - data[idx] = target; - data[target * ngens + gen] = coset; - - if (path.get(target).from_idx == -1) { - path.put(coset, gen, target); - } - } - - int Cosets::get(int coset, int gen) const { - return data[coset * ngens + gen]; - } - - int Cosets::get(int idx) const { - return data[idx]; - } - - size_t Cosets::size() const { - return path.size(); - } - - Rel::Rel(int a, int b, int m) - : gens({a, b}), mult(m) { - } - - Rel Rel::shift(int off) const { - return Rel(gens[0] + off, gens[1] + off, mult); - } - - Group::Group(int ngens, const std::vector &rels, std::string name) - : ngens(ngens), name(std::move(name)) { - _mults.resize(ngens); - - for (auto &mult : _mults) { - mult.resize(ngens, 2); - } - - for (const auto &rel : rels) { - set(rel); - } - } - - void Group::set(const Rel &r) { - _mults[r.gens[0]][r.gens[1]] = r.mult; - _mults[r.gens[1]][r.gens[0]] = r.mult; - } - - int Group::get(int a, int b) const { - return _mults[a][b]; - } - - std::vector Group::rels() const { - std::vector res; - for (int i = 0; i < ngens - 1; ++i) { - for (int j = i + 1; j < ngens; ++j) { - res.emplace_back(i, j, get(i, j)); - } - } - return res; - } - SubGroup Group::subgroup(const std::vector &gens) const { return SubGroup(*this, gens); } - - Group Group::product(const Group &other) const { - std::stringstream ss; - ss << name << "*" << other.name; - - Group g(ngens + other.ngens, rels(), ss.str()); - - for (const auto &rel : other.rels()) { - g.set(rel.shift(ngens)); - } - - return g; - } - - Group Group::power(int p) const { - std::stringstream ss; - ss << name << "^" << p; - - Group g(ngens * p, {}, ss.str()); - for (const auto &rel : rels()) { - for (int off = 0; off < g.ngens; off += ngens) { - g.set(rel.shift(off)); - } - } - - return g; - } - - SubGroup::SubGroup(const Group &parent, std::vector gen_map) - : Group(gen_map.size()), parent(parent) { - - std::sort(gen_map.begin(), gen_map.end()); - this->gen_map = gen_map; - - for (size_t i = 0; i < gen_map.size(); ++i) { - for (size_t j = 0; j < gen_map.size(); ++j) { - int mult = parent.get(gen_map[i], gen_map[j]); - set(Rel(i, j, mult)); - } - } - } - - Group operator*(const Group &g, const Group &h) { - return g.product(h); - } - - Group operator^(const Group &g, int p) { - return g.power(p); - } }