From 9bed7282ac90e0c6142b2602e4cadd77f28ce1f7 Mon Sep 17 00:00:00 2001 From: Cotton Seed Date: Tue, 28 Feb 2012 22:08:52 -0500 Subject: [PATCH] Added tensor_product and hom_module to algebra/module.h. --- algebra/linear_combination.h | 19 +- algebra/module.h | 366 ++++++++++++++++++++++++++++++++++- main.cpp | 50 +++++ 3 files changed, 425 insertions(+), 10 deletions(-) diff --git a/algebra/linear_combination.h b/algebra/linear_combination.h index 92e62dc..dda27ce 100644 --- a/algebra/linear_combination.h +++ b/algebra/linear_combination.h @@ -145,6 +145,17 @@ class linear_combination unsigned card () const { return v.card (); } + linear_combination tensor (const linear_combination &lc) const + { + linear_combination r (m->tensor (lc.m)); + for (linear_combination_const_iter i = *this; i; i ++) + for (linear_combination_const_iter j = lc; j; j ++) + { + r.muladd (i.val () * j.val (), m->tensor_generators (i.key (), lc.m, j.key ())); + } + return r; + } + #ifndef NDEBUG void check () const { @@ -292,7 +303,10 @@ linear_combination::show_self () const else printf (" + "); show (i.val ()); - printf ("*%d", i.key ()); + + // printf ("*%d", i.key ()); + printf ("*"); + m->show_generator (i.key ()); } } @@ -445,7 +459,8 @@ linear_combination::show_self () const first = 0; else printf ("+"); - printf ("%d", i.val ()); + // printf ("%d", i.val ()); + m->show_generator (i.val ()); } } diff --git a/algebra/module.h b/algebra/module.h index ce333ed..80aaf59 100644 --- a/algebra/module.h +++ b/algebra/module.h @@ -1,15 +1,38 @@ template class mod_map; + template class mod_span; + template class free_submodule; template class quotient_module; +template class tensor_product; +template class hom_module; /* `module' is a bigraded module over a ring R. */ template class module : public refcounted { + private: + unsigned id; + + static unsigned id_counter; + +#if 0 + static map, + ptr > direct_sum_idx; +#endif + + static map, + ptr > > tensor_product_idx; + static map, + ptr > > hom_module_idx; + public: - module () { } + module () + { + id = id_counter; + id_counter ++; + } module (const module &); // doesn't exist virtual ~module () { } @@ -28,6 +51,8 @@ class module : public refcounted // r < i <= n virtual R generator_ann (unsigned i) const = 0; + bool is_free () const { return dim () == free_rank (); } + bool is_zero (R c, unsigned i) const { if (i <= free_rank ()) @@ -53,10 +78,278 @@ class module : public refcounted multivariate_laurentpoly free_poincare_polynomial () const; multivariate_laurentpoly free_delta_poincare_polynomial () const; + ptr > tensor (ptr > m) const + { + basedvector >, 1> factors (2); + factors[1] = this; + factors[2] = m; + return tensor (factors); + } + + ptr > hom (ptr > to) const; + + pair + generator_factors (ptr > m, unsigned g) const + { + pair p ((g - 1) % dim () + 1, + (g - 1) / dim () + 1); + assert (g == tensor_generators (p.first, m, p.second)); + return p; + } + + static ptr > tensor (basedvector >, 1> compound_factors); + + unsigned tensor_generators (unsigned i, ptr > m, unsigned j) const + { + return (i - 1) + (j - 1) * dim () + 1; + } + + virtual void append_tensor_factors (basedvector >, 1> &factors) const + { + factors.append (this); + } + void show_self () const; void display_self () const; }; +template unsigned module::id_counter = 1; +template map, + ptr > > module::tensor_product_idx; + +template map, + ptr > > module::hom_module_idx; + +#if 0 +template +class direct_sum : public module +{ + unsigned n; + basedvector >, 1> summands; + + public: + direct_sum (basedvector >, 1> summands_) + : n(0), + summands(summands_) + { +#ifndef NDEBUG + for (unsigned i = 1; i <= terms.size (); i ++) + assert (terms[i]->is_free ()); +#endif + + for (unsigned i = 1; i <= terms.size (); i ++) + n += terms[i]->dim (); + } + + unsigned dim () const { return n; } + unsigned free_rank () const { return n; } + + // ??? + grading generator_grading (unsigned i) const { abort (); } + void show_generator (unsigned i) const { abort (); } +}; +#endif + +template +class tensor_product : public module +{ + unsigned n; + basedvector >, 1> factors; + + basedvector generator_factors (unsigned g) const; + + public: + tensor_product (basedvector >, 1> factors_) + : n(1), + factors(factors_) + { +#ifndef NDEBUG + for (unsigned i = 1; i <= factors.size (); i ++) + assert (factors[i]->is_free ()); +#endif + + for (unsigned i = 1; i <= factors.size (); i ++) + n *= factors[i]->dim (); + } + ~tensor_product () { } + + unsigned dim () const { return n; } + unsigned free_rank () const { return n; } + + grading generator_grading (unsigned i) const; + void show_generator (unsigned i) const; + R generator_ann (unsigned i) const { return R (0); } + + unsigned tensor_generators (basedvector gs) const; + + void append_tensor_factors (basedvector >, 1> &pfactors) const + { + for (unsigned i = 1; i <= factors.size (); i ++) + pfactors.append (factors[i]); + } +}; + +template ptr > +module::tensor (basedvector >, 1> compound_factors) +{ + basedvector >, 1> factors; + for (unsigned i = 1; i <= compound_factors.size (); i ++) + compound_factors[i]->append_tensor_factors (factors); + + basedvector factor_ids (factors.size ()); + for (unsigned i = 1; i <= factors.size (); i ++) + factor_ids[i] = factors[i]->id; + + pair > &, bool> p = tensor_product_idx.find (factor_ids); + if (!p.second) + p.first = new tensor_product (factors); + return p.first; +} + +template grading +tensor_product::generator_grading (unsigned i) const +{ + basedvector gs = generator_factors (i); + assert (gs.size () == factors.size ()); + + grading gr; + for (unsigned i = 1; i <= factors.size (); i ++) + gr += factors[i]->generator_grading (gs[i]); + + return gr; +} + +template void +tensor_product::show_generator (unsigned i) const +{ + basedvector gs = generator_factors (i); + assert (gs.size () == factors.size ()); + + printf ("o("); + for (unsigned i = 1; i <= factors.size (); i ++) + { + if (i > 1) + printf (","); + factors[i]->show_generator (gs[i]); + } + printf (")"); +} + +template unsigned +tensor_product::tensor_generators (basedvector gs) const +{ + assert (gs.size () == factors.size ()); + + unsigned r = gs[gs.size ()] - 1; + for (unsigned i = gs.size () - 1; i >= 1; i --) + { + r *= factors[i]->dim (); + r += gs[i] - 1; + } + r ++; + + return r; +} + +template basedvector +tensor_product::generator_factors (unsigned g) const +{ + basedvector r (factors.size ()); + + unsigned g0 = g; + + g --; + for (unsigned i = 1; i <= factors.size (); i ++) + { + r[i] = (g % factors[i]->dim ()) + 1; + g /= factors[i]->dim (); + } + assert (g == 0); + assert (tensor_generators (r) == g0); + + return r; +} + +template +class hom_module : public module +{ + public: + unsigned n; + ptr > from; + ptr > to; + + public: + hom_module (ptr > from_, + ptr > to_) + : from(from_), to(to_) + { + assert (from->is_free () + && to->is_free ()); + n = from->dim () * to->dim (); + } + ~hom_module () { } + + // e_ij -> ij + pair generator_indices (unsigned g) const + { + unsigned d = from->dim (); + unsigned g0 = g; + + g --; + pair p ((g % d) + 1, + (g / d) + 1); + + assert (generator (p.first, p.second) == g0); + + return p; + } + + // ij -> e_ij + unsigned generator (unsigned i, unsigned j) const + { + return (i - 1) + (j - 1) * from->dim () + 1; + } + + unsigned dim () const { return n; } + unsigned free_rank () const { return n; } + + grading generator_grading (unsigned i) const; + void show_generator (unsigned i) const; + R generator_ann (unsigned i) const { return R (0); } + + linear_combination map_as_element (const mod_map &m) const; +}; + +template ptr > +module::hom (ptr > to) const +{ + pair > &, bool> p = hom_module_idx.find (pair + (id, to->id)); + if (!p.second) + p.first = new hom_module (this, to); + return p.first; +} + +template grading +hom_module::generator_grading (unsigned i) const +{ + pair p = generator_indices (i); + return (to->generator_grading (p.second) + - from->generator_grading (p.first)); +} + +template void +hom_module::show_generator (unsigned i) const +{ + pair p = generator_indices (i); + + printf ("("); + from->show_generator (p.first); + printf (" -> "); + to->show_generator (p.second); + printf (")"); +} + template class base_module : public module { @@ -287,10 +580,10 @@ template class composition_impl : public map_impl { // f(g(x)) - ptr > f, g; + ptr > f, g; public: - composition_impl (ptr > f_, ptr > g_) + composition_impl (ptr > f_, ptr > g_) : map_impl(g_->from, f_->to), f(f_), g(g_) @@ -304,6 +597,30 @@ class composition_impl : public map_impl } }; +template +class tensor_impl : public map_impl +{ + // f\otimes g + ptr > f, g; + + public: + tensor_impl (ptr > f_, ptr > g_) + : map_impl(f_->from->tensor (g_->from), + f_->to->tensor (g_->from)), + f(f_), + g(g_) + { + } + + linear_combination column (unsigned i) const + { + pair p = f->from->generator_factors (g->from, i); + + // ?? + return f->column (p.first).tensor (g->column (p.second)); + } +}; + template class map_builder { @@ -349,9 +666,12 @@ map_builder::init () template class mod_map { - ptr > impl; + // ??? + enum impl_ctor { IMPL }; + + ptr > impl; - mod_map (ptr > impl_) : impl(impl_) { } + mod_map (impl_ctor, ptr > impl_) : impl(impl_) { } public: mod_map () { } @@ -389,13 +709,16 @@ class mod_map mod_map &operator = (const mod_map &m) { impl = m.impl; return *this; } + ptr > domain () const { return impl->from; } + ptr > codomain () const { return impl->to; } + bool operator == (const mod_map &m) const { assert (impl->from == m.impl->from); assert (impl->to == m.impl->to); for (unsigned i = 1; i <= impl->from->dim (); i ++) { - if (impl->columns (i) != m.impl->columns (i)) + if (impl->column (i) != m.impl->column (i)) return 0; } return 1; @@ -420,7 +743,17 @@ class mod_map linear_combination operator [] (unsigned i) const { return impl->column (i); } linear_combination map (const linear_combination &lc) const { return impl->map (lc); } - mod_map compose (const mod_map &m) const { return new composition_impl (impl, m.impl); } + mod_map compose (const mod_map &m) const + { + return mod_map (IMPL, + new composition_impl (impl, m.impl)); + } + + mod_map tensor (const mod_map &m) const + { + return mod_map (IMPL, + new tensor_impl (impl, m.impl)); + } // ?? add and other map operations should not be explicit mod_map operator + (const mod_map &m) const; @@ -457,6 +790,21 @@ class mod_map void display_self () const; }; +template linear_combination +hom_module::map_as_element (const mod_map &m) const +{ + assert (from == m.domain () + && to == m.codomain ()); + + linear_combination r (this); + for (unsigned i = 1; i <= from->dim (); i ++) + { + for (linear_combination_const_iter j = m.column (i); j; j ++) + r.muladd (j.val (), generator (i, j.key ())); + } + return r; +} + template class mod_span { @@ -1319,7 +1667,9 @@ mod_map::display_self () const show_self (); newline (); for (unsigned i = 1; i <= impl->from->dim (); i ++) { - printf (" %d: ", i); + printf (" %d ", i); + impl->from->show_generator (i); + printf (": "); show (column (i)); newline (); } diff --git a/main.cpp b/main.cpp index 539c61c..2df7032 100644 --- a/main.cpp +++ b/main.cpp @@ -165,6 +165,55 @@ check (const dt_code &dt) int main () { + ptr > A + = new explicit_module (2, basedvector (), basedvector (2)); + ptr > B + = new explicit_module (3, basedvector (), basedvector (3)); + ptr > C + = new explicit_module (3, basedvector (), basedvector (3)); + ptr > D + = new explicit_module (2, basedvector (), basedvector (2)); + ptr > E + = new explicit_module (2, basedvector (), basedvector (3)); + ptr > F + = new explicit_module (2, basedvector (), basedvector (2)); + + map_builder fb (A, B); + fb[1].muladd (2, 1); + fb[1].muladd (3, 2); + fb[2].muladd (-5, 2); + fb[2].muladd (4, 3); + mod_map f (fb); + display ("f:\n", f); + + map_builder gb (C, D); + gb[1].muladd (1, 1); + gb[2].muladd (3, 1); + gb[2].muladd (-2, 2); + gb[3].muladd (-6, 2); + mod_map g (gb); + display ("g:\n", g); + + map_builder hb (E, F); + hb[1].muladd (3, 2); + hb[2].muladd (-3, 1); + mod_map h (hb); + display ("h:\n", h); + + mod_map fg = f.tensor (g); + display ("fg:\n", fg); + + ptr > AB_C = (A->tensor (B))->tensor (C), + A_BC = A->tensor (B->tensor (C)); + assert (AB_C == A_BC); + + assert ((f.tensor (g)).tensor (h) == f.tensor (g.tensor (h))); + + ptr > homAB = A->hom (B); + linear_combination x = homAB->map_as_element (f); + display ("x:\n", x); + +#if 0 for (unsigned i = 1; i <= 14; i ++) { for (unsigned j = 1; j <= mt_links (i, 0); j ++) @@ -173,6 +222,7 @@ main () for (unsigned j = 1; j <= mt_links (i, 1); j ++) check (mt_link (i, 1, j)); } +#endif #if 0 knot_diagram kd (rolfsen_knot (8, 19));