diff --git a/algebra/Z2.h b/algebra/Z2.h index 3765fb9..4245c7f 100644 --- a/algebra/Z2.h +++ b/algebra/Z2.h @@ -15,6 +15,7 @@ class Z2 Z2 (bool v_) : v(v_) { } Z2 (const Z2 &x) : v(x.v) { } Z2 (copy, const Z2 &x) : v(x.v) { } + Z2 (reader &r) { v = r.read_bool (); } ~Z2 () { } Z2 &operator = (const Z2 &x) { v = x.v; return *this; } @@ -64,6 +65,7 @@ class Z2 } static void show_ring () { printf ("Z2"); } + void write_self (writer &w) const { w.write_bool (v); } void show_self () const { printf ("%d", (int)v); } void display_self () const { printf ("%d\n", (int)v); } }; diff --git a/algebra/grading.h b/algebra/grading.h index 4fec9b0..cbd3972 100644 --- a/algebra/grading.h +++ b/algebra/grading.h @@ -8,6 +8,12 @@ class grading grading () : h(0), q(0) { } grading (int h_, int q_) : h(h_), q(q_) { } grading (const grading &gr) : h(gr.h), q(gr.q) { } + grading (reader &r) + { + h = r.read_int (); + q = r.read_int (); + } + ~grading () { } grading &operator = (const grading &gr) { h = gr.h; q = gr.q; return *this; } @@ -45,7 +51,13 @@ class grading } grading mirror_grading (unsigned nplus, unsigned nminus, bool torsion) const; - + + void write_self (writer &w) const + { + w.write_int (h); + w.write_int (q); + } + void show_self () const; void display_self () const; }; diff --git a/algebra/linear_combination.h b/algebra/linear_combination.h index a53727a..c8b0604 100644 --- a/algebra/linear_combination.h +++ b/algebra/linear_combination.h @@ -39,6 +39,13 @@ class linear_combination for (typename map::const_iter i = lc.v; i; i ++) v.push (i.key (), R (COPY, i.val ())); } + + linear_combination (reader &r) + { + m = r.read_mod (); + v = map (r); + } + ~linear_combination () { } linear_combination &operator = (const linear_combination &lc) @@ -164,6 +171,12 @@ class linear_combination assert (!m->is_zero (i.val (), i.key ())); } #endif + + void write_self (writer &w) const + { + write (w, *m); + write (w, v); + } void show_self () const; void display_self () const { show_self (); newline (); } @@ -337,6 +350,12 @@ class linear_combination linear_combination (ptr m_) : m(m_) { } linear_combination (const linear_combination &lc) : m(lc.m), v(lc.v) { } linear_combination (copy, const linear_combination &lc) : m(lc.m), v(COPY, lc.v) { } + linear_combination (reader &r) + { + m = r.read_mod (); + v = set (r); + } + ~linear_combination () { } linear_combination &operator = (const linear_combination &lc) @@ -446,6 +465,12 @@ class linear_combination void check () const; #endif + void write_self (writer &w) const + { + write (w, *m); + write (w, v); + } + void show_self () const; void display_self () const { show_self (); newline (); } }; diff --git a/algebra/module.h b/algebra/module.h index 62d5625..6ae0f87 100644 --- a/algebra/module.h +++ b/algebra/module.h @@ -14,10 +14,15 @@ template class module : public refcounted { private: + friend class reader; + friend class writer; + unsigned id; static unsigned id_counter; + static basedvector >, 1> id_module; + static map, ptr > > direct_sum_idx; static map, @@ -28,8 +33,11 @@ class module : public refcounted public: module () { - id = id_counter; id_counter ++; + id = id_counter; + + id_module.append (this); + assert (id_module.size () == id_counter); } module (const module &) = delete; virtual ~module () { } @@ -49,6 +57,8 @@ class module : public refcounted // r < i <= n virtual R generator_ann (unsigned i) const = 0; + set gradings () const; + bool is_free () const { return dim () == free_rank (); } bool is_zero (R c, unsigned i) const @@ -143,11 +153,16 @@ class module : public refcounted factors.append (this); } + ptr > graded_piece (grading hq) const; + + void write_self (writer &w) const { w.write_mod (this); } void show_self () const; void display_self () const; }; -template unsigned module::id_counter = 1; +template unsigned module::id_counter = 0; + +template basedvector >, 1> module::id_module; template map, ptr > > module::direct_sum_idx; @@ -542,6 +557,9 @@ class free_submodule : public module linear_combination restrict (linear_combination v0) const; ptr > restrict_submodule (ptr > m) const; + + ptr > intersection (ptr > m) const; + ptr > plus (ptr > m) const; }; template @@ -854,6 +872,15 @@ class mod_map mod_map (const map_builder &b) : impl(new explicit_map_impl (b.from, b.to, b.columns)) { } + + mod_map (reader &r) + { + ptr > from = r.read_mod (); + ptr > to = r.read_mod (); + basedvector, 1> columns (r); + impl = new explicit_map_impl (from, to, columns); + } + ~mod_map () { } mod_map &operator = (const mod_map &m) { impl = m.impl; return *this; } @@ -945,6 +972,14 @@ class mod_map // ??? basedvector, 1> explicit_columns () const; + void write_self (writer &w) const + { + // write explicitly + write (w, *impl->from); + write (w, *impl->to); + write (w, explicit_columns ()); + } + void show_self () const; void display_self () const; }; @@ -1445,6 +1480,35 @@ module::free_delta_poincare_polynomial () const return r; } +template set +module::gradings () const +{ + set gs; + for (unsigned i = 1; i <= dim (); i ++) + gs += generator_grading (i); + return gs; +} + +template ptr > +module::graded_piece (grading hq) const +{ + basedvector, 1> s; + for (unsigned i = 1; i <= dim (); i ++) + { + grading ihq = generator_grading (i); + if (ihq.h == hq.h + && ihq.q == hq.q) + { + linear_combination v (this); + v.muladd (1, i); + s.append (v); + } + } + + mod_span span (this, s); + return submodule (span); +} + template void module::show_self () const { @@ -1536,7 +1600,7 @@ mod_map::restrict_from (ptr > new_from) const basedvector, 1> v (new_from->dim ()); for (unsigned i = 1; i <= new_from->dim (); i ++) v[i] = map (new_from->inject_generator (i)); - return new explicit_map_impl (new_from, impl->to, v); + return mod_map (IMPL, new explicit_map_impl (new_from, impl->to, v)); } template mod_map @@ -1560,7 +1624,7 @@ mod_map::restrict (ptr > new_from, basedvector, 1> v (new_from->dim ()); for (unsigned i = 1; i <= new_from->dim (); i ++) v[i] = new_to->restrict (map (new_from->inject_generator (i))); - return new explicit_map_impl (new_from, new_to, v); + return mod_map (IMPL, new explicit_map_impl (new_from, new_to, v)); } template linear_combination @@ -1606,6 +1670,93 @@ free_submodule::restrict_submodule (ptr > m) const return this->submodule (span2); } +template ptr > +free_submodule::intersection (ptr > m) const +{ + assert (parent == m->parent); + + unsigned md = m->dim (), + d = dim (); + + basedvector, 1> intr; + + basedvector, 1> hperp, + hproj; + basedvector hpivots; + for (unsigned i = 1; i <= md; i ++) + { + linear_combination perp (COPY, m->gens[i]), + proj (parent); + + for (unsigned j = 1; j <= d; j ++) + { + unsigned k = pivots[j]; + if (perp % k) + { + const linear_combination &g = gens[j]; + R c = g(k); + R d = perp(k); + + assert (c | d); + R q = d.div (c); + + perp.mulsub (q, g); + proj.mulsub (q, g); + + assert (! (perp % k)); + } + } + + for (unsigned j = 1; j <= hpivots.size (); j ++) + { + unsigned k = hpivots[j]; + if (perp % k) + { + const linear_combination &h = hperp[j]; + R c = h(k); + R d = perp(k); + + assert (c | d); + R q = d.div (c); + + perp.mulsub (q, h); + proj.mulsub (q, hproj[j]); + + assert (! (perp % k)); + } + + } + + if (perp == 0) + intr.append (proj); + else + { + hperp.append (perp); + hproj.append (proj); + hpivots.append (perp.head ().first); + } + } + + mod_span span (parent, intr); + return parent->submodule (span); +} + +template ptr > +free_submodule::plus (ptr > m) const +{ + assert (parent == m->parent); + + basedvector, 1> s; + for (unsigned i = 1; i <= dim (); i ++) + s.append (gens[i]); + + for (unsigned i = 1; i <= m->dim (); i ++) + s.append (m->gens[i]); + + mod_span span (parent, s); + return parent->submodule (span); +} + template bool mod_map::homogeneous () const { @@ -1655,7 +1806,7 @@ mod_map::kernel () const to = impl->to; basedvector, 1> from_xs (from->dim ()); - for (unsigned i = 1; i <= to->dim (); i ++) + for (unsigned i = 1; i <= from->dim (); i ++) { linear_combination x (from); x.muladd (1, i); @@ -1835,3 +1986,59 @@ mod_map::display_self () const newline (); } } + +// ??? io + +template void +writer::write_mod (ptr > m) +{ + pair p = aw->id_io_id.find (m->id_counter); + if (p.second) + { + write_int ((int)p.first); + } + else + { + ++ aw->io_id_counter; + unsigned io_id = aw->io_id_counter; + + p.first = io_id; + + write_int (- (int)io_id); + + unsigned n = m->dim (), + r = m->free_rank (); + write_unsigned (n); + write_unsigned (r); + for (unsigned i = 1; i <= n; i ++) + write (*this, m->generator_grading (i)); + for (unsigned i = r + 1; i <= n; i ++) + write (*this, m->generator_ann (i)); + } +} + +template ptr > +reader::read_mod () +{ + int io_id = read_int (); + if (io_id < 0) + { + unsigned n = read_unsigned (); + unsigned r = read_unsigned (); + basedvector gr (n); + for (unsigned i = 1; i <= n; i ++) + gr[i] = grading (*this); + basedvector ann (n - r); + for (unsigned i = r + 1; i <= n; i ++) + ann[i - r] = R (*this); + + ptr > m = new explicit_module (r, ann, gr); + ar->io_id_id.push ((unsigned)(-io_id), m->id); + return m; + } + else + { + unsigned id = ar->io_id_id(io_id); + return module::id_module[id]; + } +} diff --git a/lib/io.cpp b/lib/io.cpp index 336a191..d1bb53e 100644 --- a/lib/io.cpp +++ b/lib/io.cpp @@ -1,5 +1,6 @@ -#include +// #include +#include void writer::write_int (int x) diff --git a/lib/io.h b/lib/io.h index 80bf97d..b995fde 100644 --- a/lib/io.h +++ b/lib/io.h @@ -1,12 +1,18 @@ +template class module; + +class algebra_writer; +class algebra_reader; + class writer { - // don't use leb128 enconding. for backward compatibility. + public: bool raw; + algebra_writer *aw; public: writer (const writer &) = delete; - writer (bool raw_ = false) : raw(raw_) { } + writer (bool raw_ = false) : raw(raw_), aw(0) { } virtual ~writer () = default; writer &operator = (const writer &) = delete; @@ -19,16 +25,18 @@ class writer void write_int (int x); void write_unsigned (unsigned x); void write_uint64 (uint64 x); - virtual void write_mpz (const mpz_t x); + + template void write_mod (ptr > m); }; class reader { bool raw; + algebra_reader *ar; public: reader (const reader &) = delete; - reader (bool raw_) : raw(raw_) { } + reader (bool raw_) : raw(raw_), ar(0) { } virtual ~reader () = default; reader &operator = (const reader &) = delete; @@ -60,6 +68,8 @@ class reader unsigned read_unsigned (); uint64 read_uint64 (); virtual void read_mpz (mpz_t x); + + template ptr > read_mod (); }; extern FILE *open_file (const std::string &file, const char *mode); diff --git a/lib/lib.h b/lib/lib.h index b507b58..0a7faa8 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -158,11 +158,6 @@ void stderror (const char *fmt, ...); int alpha_to_int (char c); -#include - -#include -#include - using std::tuple; using std::get; using std::make_tuple; @@ -170,6 +165,11 @@ using std::tie; using std::ignore; using std::initializer_list; +#include +#include + +#include + #include #include @@ -194,7 +194,6 @@ inline int random_int (int from, int to) #include #include #include - #include #include @@ -212,3 +211,23 @@ struct hasher : public std::unary_function #include #include #include + +// ??? io + +class algebra_writer +{ +public: + // modules + unsigned io_id_counter; + map id_io_id; + + algebra_writer () : io_id_counter(0) { } + ~algebra_writer () { } +}; + +class algebra_reader +{ +public: + map io_id_id; + +}; diff --git a/main.cpp b/main.cpp index b17ce9a..5c884a5 100644 --- a/main.cpp +++ b/main.cpp @@ -277,6 +277,164 @@ load (map c (kd); + mod_map d = c.compute_d (1, 0, 0, 0, 0); + + chain_complex_simplifier s (c.khC, d, 1); + + steenrod_square sq (c, d, s); + mod_map sq1 = sq.sq1 (); + mod_map sq2 = sq.sq2 (); + + assert (sq1.compose (sq1) == 0); + assert (sq2.compose (sq2) + sq1.compose (sq2).compose (sq1) == 0); + + display ("sq1:\n", sq1); + display ("sq2:\n", sq2); + + writer w ("sqtest.dat"); + write (w, sq1); + write (w, sq2); +#endif + +#if 1 +#if 0 + reader r ("sqtest.dat"); + + knot_desc kd (knot_desc::ROLFSEN, 8, 19); + mod_map sq1 (r); + mod_map sq2 (r); + + ptr > H = sq1.domain (); + + display ("sq1:\n", sq1); + display ("sq2:\n", sq2); +#endif + + for (unsigned i = 1; i <= 10; i ++) + for (unsigned j = 1; j <= rolfsen_crossing_knots (i); j ++) + { +#if 0 + // (Knot Atlas) L10n18 + int xings[10][4] = { + { 6, 1, 7, 2 }, + { 18, 7, 19, 8 }, + { 4,19,1,20 }, + { 5,12,6,13 }, + { 8,4,9,3 }, + { 13,17,14,16 }, + { 9,15,10,14 }, + { 15,11,16,10 }, + { 11,20,12,5 }, + { 2,18,3,17 }, + }; + knot_diagram kd (planar_diagram ("L10n18", 10, xings)); +#endif + + // (Knot Atlas) L10n102 + int xings[10][4] = { + { 6,1,7,2 }, { 10,3,11,4 }, { 14,7,15,8 }, { 8,13,5,14 }, { 11,18,12,19 }, { 15,20,16,17 }, { 19,16,20,9 }, { 17,12,18,13 }, { 2,5,3,6 }, { 4,9,1,10 }, + }; + knot_diagram kd (planar_diagram ("L10n102", 10, xings)); + + // knot_diagram kd (rolfsen_knot (i, j)); + // knot_diagram kd (mt_link (10, 0, 18)); + + // show (kd); newline (); + printf ("%s ", kd.name.c_str ()); + + cube c (kd); + mod_map d = c.compute_d (1, 0, 0, 0, 0); + + chain_complex_simplifier s (c.khC, d, 1); + + steenrod_square sq (c, d, s); + + mod_map sq1 = sq.sq1 (); + mod_map sq2 = sq.sq2 (); + + assert (sq1.compose (sq1) == 0); + assert (sq2.compose (sq2) + sq1.compose (sq2).compose (sq1) == 0); + + ptr > H = sq1.domain (); + + bool first = 1; + + // ??? + set gs = H->gradings (); + for (set_const_iter i = gs; i; i ++) + { + grading hq = i.val (), + h1q (hq.h + 1, hq.q), + h2q (hq.h + 2, hq.q); + + // printf ("(%d, %d):\n", hq.h, hq.q); + + ptr > H_hq = H->graded_piece (hq), + H_h1q = H->graded_piece (h1q), + H_h2q = H->graded_piece (h2q); + + mod_map whole = sq2.restrict (H_hq, H_h2q), + tail = sq1.restrict (H_hq, H_h1q), + head = sq1.restrict (H_h1q, H_h2q); + + ptr > whole_im = whole.image (), + tail_ker = tail.kernel (), + head_im = head.image (); + ptr > inter = whole_im->intersection (head_im); + + mod_map whole_res = whole.restrict_from (tail_ker); + ptr > whole_res_im = whole_res.image (); + + ptr > res_inter = whole_res_im->intersection (head_im); + + int r1 = whole_im->dim (); + int r2 = whole_res_im->dim (); + int r3 = inter->dim (); + int r4 = res_inter->dim (); + + if (r1 == 0 + && r2 == 0 + && r3 == 0 + && r4 == 0) + continue; + + // printf (" r = (%d, %d, %d, %d)\n", r1, r2, r3, r4); + + int s1 = r2 - r4, + s2 = r1 - r2 - r3 + r4, + s3 = r4, + s4 = r3 - r4; + + if (first) + { +#if 0 + show (kd); + printf (": "); +#endif + first = 0; + } + else + printf (", "); + printf ("(%d, %d) -> (%d, %d, %d, %d)", + hq.h, hq.q, + s1, s2, s3, s4); + } + // if (!first) + newline (); + } +#endif + +#if 0 + // knot_diagram kd (htw_knot (12, 0, 48)); + knot_diagram kd (htw_knot (10, 1, 23)); + show (kd); newline (); +#endif + #if 0 for (int a = 1; a >= 0; a --) for (unsigned i = 1; i <= 9; i ++) @@ -350,7 +508,7 @@ main () } #endif -#if 1 +#if 0 compute_show_kh_sq (knot_desc (knot_desc::ROLFSEN, 8, 19)); map= 0; a --) - for (unsigned i = 1; i <= 10; i ++) - for (unsigned j = 1; j <= rolfsen_crossing_knots (i); j += 4000) + for (unsigned i = 14; i >= 1; i --) + { + if (i <= 10) { - work.append (knot_desc (ROLFSEN, i, j)); + for (unsigned j = 1; j <= rolfsen_crossing_knots (i); j += block_size) + { + work.append (knot_desc (ROLFSEN, i, j)); + } } - - for (int a = 1; a >= 0; a --) - for (unsigned i = 1; i <= 14; i ++) - for (unsigned j = 1; j <= htw_knots (i); j += 4000) + + for (unsigned j = 1; j <= htw_knots (i); j += block_size) { work.append (knot_desc (HTW, i, j)); } - - for (int a = 1; a >= 0; a --) - for (unsigned i = 1; i <= 13; i ++) - for (unsigned j = 1; j <= mt_links (i); j += 4000) + + if (i <= 13) { - work.append (knot_desc (MT, i, j)); + for (unsigned j = 1; j <= mt_links (i); j += block_size) + { + work.append (knot_desc (MT, i, j)); + } } + } int ntasks = num_tasks (); @@ -80,9 +85,7 @@ master () void compute_kh_sq (map, - multivariate_laurentpoly, - multivariate_laurentpoly > > &knot_kh_sq, + triple >, mod_map, mod_map > > &knot_kh_sq, knot_desc &desc) { knot_diagram kd = desc.diagram (); @@ -96,6 +99,7 @@ compute_kh_sq (map d = c.compute_d (1, 0, 0, 0, 0); chain_complex_simplifier s (c.khC, d, 1); + assert (s.new_d == 0); steenrod_square sq (c, d, s); mod_map sq1 = sq.sq1 (); @@ -104,18 +108,8 @@ compute_kh_sq (map P = s.new_C->free_poincare_polynomial (); - - ptr > sq1_im = sq1.image (); - multivariate_laurentpoly sq1_P = sq1_im->free_poincare_polynomial (); - - ptr > sq2_im = sq2.image (); - multivariate_laurentpoly sq2_P = sq2_im->free_poincare_polynomial (); - knot_kh_sq.push (desc, - triple, - multivariate_laurentpoly, - multivariate_laurentpoly > (P, sq1_P, sq2_P)); + triple >, mod_map, mod_map > (s.new_C, sq1, sq2)); } void @@ -136,9 +130,7 @@ slave () desc.j = (knot_desc::table)recv_int (); map, - multivariate_laurentpoly, - multivariate_laurentpoly > > knot_kh_sq; + triple >, mod_map, mod_map > > knot_kh_sq; char buf[1000]; if (desc.t == TORUS) @@ -167,7 +159,7 @@ slave () j0); for (unsigned j = j0; - j <= std::min (j0 + 4000, + j <= std::min (j0 + block_size - 1, desc.table_crossing_knots ()); j ++) {