template class spanning_tree_complex { public: // twisted by default typedef fraction_field > R; const knot_diagram &kd; directed_multigraph bg; basedvector edge_height; basedvector, 1> trees; map, unsigned> tree_idx; public: ptr > C; public: spanning_tree_complex (const knot_diagram &kd_); grading tree_grading (unsigned i) const; void show_tree (unsigned i) const; mod_map twisted_d2 () const; }; template class tree_generators { typedef fraction_field > R; const spanning_tree_complex &c; public: tree_generators (const tree_generators &g) : c(g.c) { } tree_generators (const spanning_tree_complex &c_) : c(c_) { } ~tree_generators () { } tree_generators &operator = (const tree_generators &); // doesn't exist unsigned dim () const { return c.trees.size (); } unsigned free_rank () const { return c.trees.size (); } grading generator_grading (unsigned i) const { return c.tree_grading (i); } void show_generator (unsigned i) const { c.show_tree (i); } R generator_ann (unsigned i) const { abort (); } }; template spanning_tree_complex::spanning_tree_complex (const knot_diagram &kd_) : kd(kd_) { bg = kd.black_graph (edge_height); trees = bg.spanning_trees (); for (unsigned i = 1; i <= trees.size (); i ++) tree_idx.push (trees[i], i); C = new base_module > (tree_generators (*this)); } template grading spanning_tree_complex::tree_grading (unsigned i) const { unsigned h = 0; for (unsigned j = 1; j <= bg.num_edges (); j ++) { if (trees[i] % j) h += edge_height[j]; else h += (1 - edge_height[j]); } // return grading (0, - h + kd.nplus); // ??? homologically graded return grading (h - kd.nminus, h + kd.nplus - 2 * kd.nminus); } template void spanning_tree_complex::show_tree (unsigned i) const { // ??? printf ("%d", i); } extern map find_cycle (const directed_multigraph &bg, set edges, unsigned f, unsigned f_to); template mod_map > > spanning_tree_complex::twisted_d2 () const { assert (kd.marked_edge); mod_map d (C); basedvector edge_weight (kd.num_edges ()); for (unsigned i = 1; i <= kd.num_edges (); i ++) edge_weight[i] = 1; // (1 << i); for (unsigned i = 1; i <= trees.size (); i ++) { set t = trees[i]; smallbitset r (kd.n_crossings); for (unsigned k = 1; k <= kd.n_crossings; k ++) { if ((edge_height[k] == 1) == (t % k)) r.push (k); } smoothing s (kd, r); for (set_const_iter ee = t; ee; ee ++) { unsigned e = ee.val (); if (edge_height[e] != 0) continue; for (unsigned f = 1; f <= bg.num_edges (); f ++) { if (edge_height[f] != 1 || (t % f)) continue; set t2 (COPY, t); t2.yank (e); t2.push (f); unsigned j = tree_idx(t2, 0); if (j == 0) continue; bool neg = 0; for (unsigned a = kd.marked_edge;;) { unsigned p = s.edge_to (kd, a); if (kd.ept_crossing[p] == e) { if (s.is_crossing_from_ept (kd, r, p)) neg = s.crossing_from_inside (kd, r, e); else neg = s.crossing_to_inside (kd, r, e); break; } else if (kd.ept_crossing[p] == f) { if (s.is_crossing_from_ept (kd, r, p)) neg = s.crossing_from_inside (kd, r, f); else neg = s.crossing_to_inside (kd, r, f); break; } a = s.next_edge (kd, r, a); assert (a != kd.marked_edge); } set neither (COPY, t); neither.yank (e); smallbitset neither_r (kd.n_crossings); for (unsigned k = 1; k <= kd.n_crossings; k ++) { if ((edge_height[k] == 1) == (neither % k)) neither_r.push (k); } smoothing neither_s (kd, neither_r); set both (COPY, t); both.push (f); unsigned A = 0; for (unsigned k = 1; k <= kd.num_edges (); k ++) { if (neither_s.edge_circle[k] != neither_s.edge_circle[kd.marked_edge]) A += edge_weight[k]; } smallbitset both_r (kd.n_crossings); for (unsigned k = 1; k <= kd.n_crossings; k ++) { if ((edge_height[k] == 1) == (both % k)) both_r.push (k); } smoothing both_s (kd, both_r); unsigned B = 0; for (unsigned k = 1; k <= kd.num_edges (); k ++) { if (both_s.edge_circle[k] != both_s.edge_circle[kd.marked_edge]) B += edge_weight[k]; } R x; if (neg) x += R (1); x += R (polynomial (1), polynomial (1) + polynomial (1, A)); x += R (polynomial (1), polynomial (1) + polynomial (1, B)); d[i].muladd (x, j); } } } return d; }