diff --git a/.gitignore b/.gitignore index 0578269..2368d6d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ /main /testsurfaces /serial.cmd* +/save +*/save diff --git a/knot_diagram.cpp b/knot_diagram.cpp index 777a267..5b5e803 100644 --- a/knot_diagram.cpp +++ b/knot_diagram.cpp @@ -295,6 +295,165 @@ knot_diagram::knot_diagram (const dt_code &dt) calculate_smoothing_orientation (); } +knot_diagram::knot_diagram (sublink, + smallbitset c, + const knot_diagram &kd) + : name(kd.name), + n_crossings(0), + marked_edge(0), + nminus(0), + nplus(0) +{ + // ??? assert (!kd.marked_edge); + assert (c.card () > 0); // no empty diagrams + + // edge x component + unionfind<1> u (kd.num_edges ()); + + for (unsigned i = 1; i <= kd.n_crossings; i ++) + { + u.join (kd.ept_edge (kd.crossings[i][1]), + kd.ept_edge (kd.crossings[i][3])); + u.join (kd.ept_edge (kd.crossings[i][2]), + kd.ept_edge (kd.crossings[i][4])); + } + + assert (u.num_sets () == c.size ()); + + ullmanset<1> u_sets (kd.num_edges ()); + for (unsigned i = 1; i <= kd.num_edges (); i ++) + u_sets += u.find (i); + + ullmanset<1> sub_crossings (kd.n_crossings), + sub_edges (kd.num_edges ()); + + for (unsigned i = 1; i <= kd.num_edges (); i ++) + { + if (c % (u_sets.position (u.find (i)) + 1)) + sub_edges.push (i); + } + + // sub edge x sublink edge + unionfind<1> subu (sub_edges.card ()); + + set active_comps; + + for (unsigned i = 1; i <= kd.n_crossings; i ++) + { + unsigned c1 = u_sets.position (u.find (kd.ept_edge (kd.crossings[i][1]))) + 1, + c2 = u_sets.position (u.find (kd.ept_edge (kd.crossings[i][2]))) + 1; + + if (c % c1 + && c % c2) + { + sub_crossings.push (i); + active_comps += c1; + active_comps += c2; + } + else + { + if (c % (u_sets.position (u.find (kd.ept_edge (kd.crossings[i][1]))) + 1)) + { + subu.join (sub_edges.position (kd.ept_edge (kd.crossings[i][1])) + 1, + sub_edges.position (kd.ept_edge (kd.crossings[i][3])) + 1); + } + if (c % (u_sets.position (u.find (kd.ept_edge (kd.crossings[i][2]))) + 1)) + { + subu.join (sub_edges.position (kd.ept_edge (kd.crossings[i][2])) + 1, + sub_edges.position (kd.ept_edge (kd.crossings[i][4])) + 1); + } + } + } + + n_crossings = (sub_crossings.card () + + (c.card () - active_comps.card ())); + + assert (n_crossings > 0); + + ullmanset<1> subu_sets (sub_edges.card ()); + for (unsigned i = 1; i <= sub_edges.card (); i ++) + subu_sets += subu.find (i); + + crossings = basedvector, 1> (n_crossings); + for (unsigned i = 1; i <= n_crossings; i ++) + crossings[i] = basedvector (4); + for (ullmanset_const_iter<1> i = sub_crossings; i; i ++) + { + unsigned c = i.val (), + new_c = i.pos () + 1; + + unsigned e1 = (subu_sets.position + (subu.find (sub_edges.position (kd.ept_edge (kd.crossings[c][1])) + 1)) + 1), + e2 = (subu_sets.position + (subu.find (sub_edges.position (kd.ept_edge (kd.crossings[c][2])) + 1)) + 1), + e3 = (subu_sets.position + (subu.find (sub_edges.position (kd.ept_edge (kd.crossings[c][3])) + 1)) + 1), + e4 = (subu_sets.position + (subu.find (sub_edges.position (kd.ept_edge (kd.crossings[c][4])) + 1)) + 1); + + if (kd.is_from_ept (kd.crossings[c][1])) + crossings[new_c][1] = edge_from_ept (e1); + else + crossings[new_c][1] = edge_to_ept (e1); + + if (kd.is_from_ept (kd.crossings[c][2])) + crossings[new_c][2] = edge_from_ept (e2); + else + crossings[new_c][2] = edge_to_ept (e2); + + if (kd.is_from_ept (kd.crossings[c][3])) + crossings[new_c][3] = edge_from_ept (e3); + else + crossings[new_c][3] = edge_to_ept (e3); + + if (kd.is_from_ept (kd.crossings[c][4])) + crossings[new_c][4] = edge_from_ept (e4); + else + crossings[new_c][4] = edge_to_ept (e4); + } + + unsigned e = subu.num_sets (); + unsigned new_c = sub_crossings.card (); + for (smallbitset_const_iter i = c; i; i ++) + { + if (active_comps % i.val ()) + continue; + + unsigned e1 = (subu_sets.position + (subu.find (sub_edges.position (u_sets.nth (i.val () - 1)) + 1)) + 1); + unsigned e2 = ++ e; + unsigned c = ++ new_c; + + crossings[c][1] = edge_from_ept (e1); + crossings[c][2] = edge_to_ept (e1); + + crossings[c][3] = edge_to_ept (e2); + crossings[c][4] = edge_from_ept (e2); + } + assert (e == num_edges ()); + assert (new_c == n_crossings); + + // ?? break this out into aux function + ept_crossing = basedvector (num_epts ()); + ept_index = basedvector (num_epts ()); + for (unsigned i = 1; i <= n_crossings; i ++) + { + for (unsigned j = 1; j <= 4; j ++) + { + unsigned p = crossings[i][j]; + ept_crossing[p] = i; + ept_index[p] = j; + } + } + +#ifndef NDEBUG + check_crossings (); +#endif + + calculate_smoothing_orientation (); + calculate_nminus_nplus (); +} + knot_diagram::knot_diagram (mirror, const knot_diagram &kd) : name("mirror(" + kd.name + ")"), n_crossings(kd.n_crossings), @@ -342,6 +501,12 @@ knot_diagram::check_crossings () assert (ept_index[p] == j); } } + + for (unsigned i = 1; i <= num_edges (); i ++) + { + unsigned to = edge_to_ept (i); + assert (is_from_ept (crossings[ept_crossing[to]][add_base1_mod4 (ept_index[to], 2)])); + } } void @@ -596,6 +761,21 @@ static unsigned corner_index (unsigned x) return ((x - 1) % 4) + 1; } +unsigned +knot_diagram::num_components () const +{ + unionfind<1> u (num_edges ()); + + for (unsigned i = 1; i <= n_crossings; i ++) + { + u.join (ept_edge (crossings[i][1]), + ept_edge (crossings[i][3])); + u.join (ept_edge (crossings[i][2]), + ept_edge (crossings[i][4])); + } + return u.num_sets (); +} + directed_multigraph knot_diagram::black_graph (basedvector &bg_edge_height) const { diff --git a/knot_diagram.h b/knot_diagram.h index ac8d07a..46247aa 100644 --- a/knot_diagram.h +++ b/knot_diagram.h @@ -10,6 +10,7 @@ add_base1_mod4 (unsigned x, unsigned y) enum mirror { MIRROR }; enum connect_sum { CONNECT_SUM }; +enum sublink { SUBLINK }; class knot_diagram { @@ -96,6 +97,8 @@ class knot_diagram } bool is_smoothing_to_ept (unsigned p) const { return !is_smoothing_from_ept (p); } + unsigned num_components () const; + void orient (); void calculate_nminus_nplus (); void calculate_smoothing_orientation (); @@ -106,9 +109,9 @@ class knot_diagram public: knot_diagram () : n_crossings(0), - marked_edge(0), - nminus(0), - nplus(0) + marked_edge(0), + nminus(0), + nplus(0) { } explicit knot_diagram (const planar_diagram &pd); explicit knot_diagram (const dt_code &dt); @@ -116,6 +119,9 @@ class knot_diagram knot_diagram (connect_sum, const knot_diagram &d1, const knot_diagram &d2); + knot_diagram (sublink, + smallbitset c, + const knot_diagram &kd); knot_diagram (const std::string &name_, unsigned n_crossings_, unsigned crossings_ar[][4]); knot_diagram (const std::string &name_, const basedvector, 1> &crossings_); diff --git a/main.cpp b/main.cpp index 074fc13..539c61c 100644 --- a/main.cpp +++ b/main.cpp @@ -108,9 +108,72 @@ test_field () } } +void +check (const dt_code &dt) +{ + if (dt.num_components () > 1) + { + knot_diagram kd (dt); + kd.marked_edge = 1; + show (kd); newline (); + + cube c (kd, 1); + mod_map d = c.compute_d (1, 0, 0, 0, 0); + sseq_builder b (c.khC, d); + sseq ss = b.build_sseq (); + + unsigned n_comps = kd.num_components (); + assert (n_comps == dt.num_components ()); + + unsigned split = 1; + for (unsigned k = 1; k < unsigned_2pow (n_comps) - 1; k ++) + { + knot_diagram kd2 (SUBLINK, + smallbitset (n_comps, k), + kd); + kd2.marked_edge = 1; + unsigned n_comps2 = kd2.num_components (); + + assert (n_comps2 == unsigned_bitcount (k)); + assert (n_comps2 > 0); + assert (n_comps2 < n_comps); + + cube c2 (kd2, 1); + mod_map d2 = c2.compute_d (1, 0, 0, 0, 0); + sseq_builder b2 (c2.khC, d2); + sseq ss2 = b2.build_sseq (); + + printf (" k = %d, %d <=? %d\n", + k, + ss2.pages[1].total_rank (), + ss.pages[1].total_rank ()); + if (ss2.pages[1].total_rank () > ss.pages[1].total_rank ()) + printf (" !! COUNTEREXAMPLE\n"); + + if (unsigned_bitcount (k) == 1) + split *= ss2.pages[1].total_rank (); + } + + printf (" split %d <=? %d\n", + split, + ss.pages[1].total_rank ()); + if (split > ss.pages[1].total_rank ()) + printf (" !! COUNTEREXAMPLE\n"); + } +} + int main () { + for (unsigned i = 1; i <= 14; i ++) + { + for (unsigned j = 1; j <= mt_links (i, 0); j ++) + check (mt_link (i, 0, j)); + + for (unsigned j = 1; j <= mt_links (i, 1); j ++) + check (mt_link (i, 1, j)); + } + #if 0 knot_diagram kd (rolfsen_knot (8, 19)); cube c (kd); @@ -143,6 +206,7 @@ main () } #endif +#if 0 multivariate_laurentpoly p = -11; p.muladdeq (5, VARIABLE, 1); p.muladdeq (7, VARIABLE, 2); @@ -187,6 +251,7 @@ main () assert (m2(p) == "p"); assert (m2(q) == "q"); assert (m2(r) == "thisisr"); +#endif #if 0 test_ring (2);