class sseq_bounds { public: int minh, maxh, minq, maxq; public: sseq_bounds () { } template sseq_bounds (ptr > C, M m) { grading hq1 = m(C->generator_grading (1)); minh = maxh = hq1.h; minq = maxq = hq1.q; for (unsigned i = 2; i <= C->dim (); i ++) { grading hq = m(C->generator_grading (i)); if (hq.h < minh) minh = hq.h; if (hq.h > maxh) maxh = hq.h; if (hq.q < minq) minq = hq.q; if (hq.q > maxq) maxq = hq.q; } } sseq_bounds (int minh_, int maxh_, int minq_, int maxq_) : minh(minh_), maxh(maxh_), minq(minq_), maxq(maxq_) { } sseq_bounds (const sseq_bounds &b) : minh(b.minh), maxh(b.maxh), minq(b.minq), maxq(b.maxq) { } ~sseq_bounds () { } sseq_bounds &operator = (const sseq_bounds &b) { minh = b.minh; maxh = b.maxh; minq = b.minq; maxq = b.maxq; return *this; } unsigned width () const { return maxh - minh + 1; } unsigned height () const { return maxq - minq + 1; } bool operator == (const sseq_bounds &b) const { return minh == b.minh && maxh == b.maxh && minq == b.minq && maxq == b.maxq; } bool operator != (const sseq_bounds &b) const { return !operator == (b); } }; class sseq_page { public: /* bounds come from sseq */ unsigned k; grading dk_gr; vector > rank, im_rank; public: sseq_page () { } sseq_page (const sseq_bounds &b); template sseq_page (const sseq_bounds &b, unsigned k_, grading dk_gr_, mod_map d, M m); sseq_page (const sseq_page &pg) : k(pg.k), dk_gr(pg.dk_gr), rank(pg.rank), im_rank(pg.im_rank) { } ~sseq_page () { } bool operator == (const sseq_page &pg) const { return k == pg.k && dk_gr == pg.dk_gr && rank == pg.rank && im_rank == pg.im_rank; } bool operator != (const sseq_page &pg) const { return !operator == (pg); } unsigned total_rank () const; multivariate_laurentpoly poincare_polynomial (const sseq_bounds &b) const; multivariate_laurentpoly delta_poincare_polynomial (const sseq_bounds &b) const; unsigned homological_width (const sseq_bounds &b) const; void addeq (const sseq_bounds &b, const sseq_bounds &b2, const sseq_page &pg2); void otimes_addeq (const sseq_bounds &b, const sseq_bounds &b1, const sseq_page &pg1, const sseq_bounds &b2, const sseq_page &pg2); template void texshow (FILE *fp, const sseq_bounds &b, const char *label, M m); }; class sseq { public: sseq_bounds bounds; basedvector pages; public: sseq () { } sseq (const sseq_bounds &b, const basedvector &pages_) : bounds(b), pages(pages_) { } sseq (const sseq_bounds &b) : bounds(b) { } sseq (const sseq &ss) : bounds(ss.bounds), pages(ss.pages) { } ~sseq () { } sseq &operator = (const sseq &ss) { bounds = ss.bounds; pages = ss.pages; return *this; } sseq operator + (const sseq &ss2) const; // direct sum sseq otimes (const sseq &ss2) const; // tensor product sseq shift (int dh, int dq) const; unsigned e2_rank () const { return pages[1].total_rank (); } unsigned einf_rank () const { return pages[pages.size ()].total_rank (); } unsigned homological_width () const { return pages[1].homological_width (bounds); } bool operator == (const sseq &ss) const { return bounds == ss.bounds && pages == ss.pages; } bool operator != (const sseq &ss) const { return !operator == (ss); } template void texshow (FILE *fp, M m); }; template sseq_page::sseq_page (const sseq_bounds &b, unsigned k_, grading dk_gr_, mod_map dk, M m) : k(k_), dk_gr(dk_gr_), rank(b.width ()), im_rank(b.width ()) { dk.check_grading (dk_gr); grading m_dk_gr = m.map_delta(dk_gr); for (unsigned i = 0; i < b.width (); i ++) { vector r (b.height ()), im_r (b.height ()); for (unsigned j = 0; j < b.height (); j ++) r[j] = im_r[j] = 0; rank[i] = r; im_rank[i] = im_r; } ptr > C = dk.domain (); for (unsigned i = 1; i <= C->dim (); i ++) { grading gr = m(C->generator_grading (i)); rank[(unsigned)(gr.h - b.minh)][(unsigned)(gr.q - b.minq)] ++; } ptr > im = dk.image (); for (unsigned i = 1; i <= im->dim (); i ++) { grading gr = m(im->generator_grading (i)); im_rank[(unsigned)(gr.h - m_dk_gr.h - b.minh)][(unsigned)(gr.q - m_dk_gr.q - b.minq)] ++; } } template void sseq_page::texshow (FILE *fp, const sseq_bounds &b, const char *label, M m) { grading m_dk_gr = m.map_delta(dk_gr); unsigned dh = m_dk_gr.h, dq = m_dk_gr.q; fprintf (fp, "\ \\begin{tikzpicture}[scale=.66]\n\ \\draw[->] (0,0) -- (%d.5,0) node[right] {$t$};\n\ \\draw[->] (0,0) -- (0,%d.5) node[above] {$q$};\n\ \\draw[step=1] (0,0) grid (%d,%d);\n", b.width (), b.height (), b.width (), b.height ()); fprintf (fp, " \\draw (%.3f,-0.8) node[below] {%s};\n", ((double)b.width () + 0.5) / 2, label); /* label axes */ for (int x = b.minh; x <= b.maxh; x ++) { fprintf (fp, "\ \\draw (%d.5,-.2) node[below] {$", x - b.minh); m.x_label (fp, x); fprintf (fp, "$};\n"); } for (int y = b.minq; y <= b.maxq; y ++) { fprintf (fp, "\ \\draw (-.2,%d.5) node[left] {$", y - b.minq); m.y_label (fp, y); fprintf (fp, "$};\n"); } for (unsigned i = 0; i < b.width (); i ++) for (unsigned j = 0; j < b.height (); j ++) { int r = rank[i][j]; if (r == 1) { fprintf (fp, "\ \\fill (%d.5, %d.5) circle (.15);\n", i, j); } else if (r > 1) { fprintf (fp, "\ \\draw (%d.5, %d.5) node {$%d$};\n", i, j, r); } } for (unsigned i = 0; i < b.width (); i ++) for (unsigned j = 0; j < b.height (); j ++) { unsigned r = im_rank[i][j]; if (r == 0) continue; int dx = dh, dy = dq; // in "boxes" double h = sqrt ((double)(dx * dx + dy * dy)); double xadj = (double)dx / h * 0.3; double yadj = (double)dy / h * 0.3; fprintf (fp, " \\draw[->] (%.3f, %.3f) -- ", (double)i + 0.5 + xadj, (double)j + 0.5 + yadj); if (r > 1) fprintf (fp, "node[color=red!75!black] {$%d$} ", r); fprintf (fp, "(%.3f, %.3f);\n", (double)((int)i + dx) + 0.5 - xadj, (double)((int)j + dy) + 0.5 - yadj); } fprintf (fp, "\ \\end{tikzpicture}\n"); fflush (fp); } template void sseq::texshow (FILE *fp, M m) { unsigned n = pages.size (); for (unsigned i = 1; i <= n; i ++) { if (i == n) fprintf (fp, "$\\rank E_\\infty = \\rank E_%d = %d$ \\\\\n", pages[i].k, pages[i].total_rank ()); else fprintf (fp, "$\\rank E_%d = %d$ \\\\\n", pages[i].k, pages[i].total_rank ()); } for (unsigned i = 1; i <= n; i ++) { char buf[1000]; if (i == n) sprintf (buf, "$E_\\infty = E_{%d}$", pages[i].k); else sprintf (buf, "$E_{%d}$", pages[i].k); pages[i].texshow (fp, bounds, buf, m); } } class sseq_builder { private: typedef Z2::linear_combination linear_combination; // typedef Z2::linear_combination_iter linear_combination_iter; typedef Z2::linear_combination_const_iter linear_combination_const_iter; public: ptr > C; ullmanset<1> present; basedvector, 1> im, preim; void cancel (unsigned i, unsigned j); void cancel (unsigned d); linear_combination lc (const set &s); bool im_zero (); public: sseq_builder (const ptr > &C_, const mod_map &d); sseq build_sseq (); };