From f3d7e22f515b63cd0a993b6d4123eb941e9e494d Mon Sep 17 00:00:00 2001 From: Cotton Seed Date: Thu, 17 Jan 2013 18:43:52 -0500 Subject: [PATCH] Strengthened b'_lk to use Khovanov homology. Set up to compute sp bounds in paralllel. --- knot_diagram.cpp | 54 +++++++++++ knot_diagram.h | 4 + main.cpp | 126 ++++++++++++++++++++++---- mpimain.cpp | 227 ++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 382 insertions(+), 29 deletions(-) diff --git a/knot_diagram.cpp b/knot_diagram.cpp index f9a44fe..420a8f4 100644 --- a/knot_diagram.cpp +++ b/knot_diagram.cpp @@ -454,6 +454,60 @@ knot_diagram::knot_diagram (sublink, calculate_nminus_nplus (); } +knot_diagram::knot_diagram (disjoint_union, + const knot_diagram &kd1, + const knot_diagram &kd2) + : name(kd1.name + "+" + kd2.name), + n_crossings(kd1.n_crossings + kd2.n_crossings), + marked_edge(0), + crossings(n_crossings), + nminus(kd1.nminus + kd2.nminus), + nplus(kd1.nplus + kd2.nplus) +{ + assert (kd1.marked_edge == 0); + assert (kd2.marked_edge == 0); + + for (unsigned i = 1; i <= n_crossings; i ++) + crossings[i] = basedvector (4); + + for (unsigned i = 1; i <= kd1.n_crossings; i ++) + for (unsigned j = 1; j <= 4; j ++) + crossings[i][j] = kd1.crossings[i][j]; + + for (unsigned e = 1; e <= kd1.num_edges (); e ++) + { + if (kd1.edge_smoothing_oriented % e) + edge_smoothing_oriented.push (e); + } + + for (unsigned i = 1; i <= kd2.n_crossings; i ++) + for (unsigned j = 1; j <= 4; j ++) + crossings[kd1.n_crossings + i][j] = kd1.num_epts () + kd2.crossings[i][j]; + + for (unsigned e = 1; e <= kd2.num_edges (); e ++) + { + if (kd2.edge_smoothing_oriented % e) + edge_smoothing_oriented.push (kd1.num_edges () + e); + } + + // ?? 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 +} + knot_diagram::knot_diagram (mirror, const knot_diagram &kd) : name("mirror(" + kd.name + ")"), n_crossings(kd.n_crossings), diff --git a/knot_diagram.h b/knot_diagram.h index 89d53ca..a37f34d 100644 --- a/knot_diagram.h +++ b/knot_diagram.h @@ -11,6 +11,7 @@ add_base1_mod4 (unsigned x, unsigned y) enum mirror { MIRROR }; enum connect_sum { CONNECT_SUM }; enum sublink { SUBLINK }; +enum disjoint_union { DISJOINT_UNION }; class knot_diagram { @@ -122,6 +123,9 @@ class knot_diagram knot_diagram (sublink, smallbitset c, const knot_diagram &kd); + knot_diagram (disjoint_union, + const knot_diagram &kd1, + const knot_diagram &kd2); 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 0acd764..40eaa09 100644 --- a/main.cpp +++ b/main.cpp @@ -2262,6 +2262,106 @@ permutations (unsigned n) return permutations (v); } +template multivariate_laurentpoly +Kh_poincare_polynomial (knot_diagram &kd) +{ + cube c (kd); + mod_map d = c.compute_d (1, 0, 0, 0, 0); + chain_complex_simplifier s (c.khC, d, 0); + assert (s.new_d == 0); + return s.new_C->free_poincare_polynomial (); +} + +unsigned +compute_b_lk_weak (knot_diagram &kd) +{ + unsigned m = kd.num_components (); + assert (m > 1); + + if (m == 2) + { + unsigned total_lk = kd.total_linking_number (); + return total_lk == 0 ? 2 : total_lk; + } + + 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 (m == u.num_sets ()); + + map root_comp; + unsigned t = 0; + for (unsigned i = 1; i <= kd.num_edges (); i ++) + { + if (u.find (i) == i) + { + ++ t; + root_comp.push (i, t); + } + } + assert (t == m); + + unsigned b_lk_weak = 0; + + for (unsigned i = 1; i <= m; i ++) + for (unsigned j = i + 1; j <= m; j ++) + { + assert (i < j); + + int lk = 0; + for (unsigned x = 1; x <= kd.n_crossings; x ++) + { + unsigned r1 = root_comp(u.find (kd.ept_edge (kd.crossings[x][1]))), + r2 = root_comp(u.find (kd.ept_edge (kd.crossings[x][2]))); + if (((r1 == i) && (r2 == j)) + || ((r2 == i) && (r1 == j))) + { + if (kd.is_to_ept (kd.crossings[x][1]) == kd.is_to_ept (kd.crossings[x][4])) + lk ++; + else + lk --; + } + } + assert (is_even (lk)); + lk /= 2; + + if (lk == 0) + { + smallbitset ci (m); + ci.push (i); + + smallbitset cj (m); + cj.push (j); + + smallbitset c (m); + c.push (i); + c.push (j); + knot_diagram Lij (SUBLINK, c, kd); + + multivariate_laurentpoly P_Lij = Kh_poincare_polynomial (Lij); + + knot_diagram Li_join_Lj (DISJOINT_UNION, + knot_diagram (SUBLINK, ci, kd), + knot_diagram (SUBLINK, cj, kd)); + + multivariate_laurentpoly P_Li_join_Lj = Kh_poincare_polynomial (Li_join_Lj); + + if (P_Lij != P_Li_join_Lj) + lk = 2; // non-split + } + + b_lk_weak += abs (lk); + } + + return b_lk_weak == 0 ? 2 : b_lk_weak; +} + void compute_splitting_bounds () { @@ -2319,25 +2419,18 @@ compute_splitting_bounds () printf (" b = %d\n", b); unsigned total_lk = kd.total_linking_number (); - unsigned b_lk_weak = total_lk == 0 ? 2 : total_lk; + unsigned b_lk_weak = compute_b_lk_weak (kd); + unsigned b_lk_weaker = total_lk == 0 ? 2 : total_lk; + + printf (" b_lk_weaker = %d\n", b_lk_weaker); printf (" b_lk_weak = %d\n", b_lk_weak); - basedvector, 1> ps = permutations (m); -#if 0 - printf ("ps, |ps| = %d, m = %d:\n", ps.size (), m); - for (unsigned i = 1; i <= ps.size (); i ++) - { - basedvector p = ps[i]; - assert (p.size () == m); - - printf (" % 3d: ", i); - for (unsigned j = 1; j <= m; j ++) - printf (" %d", p[j]); - newline (); - } -#endif + assert (b_lk_weaker <= b_lk_weak); + if (b_lk_weaker < b_lk_weak) + printf (" > STRICTLY WEAKER\n"); + basedvector, 1> ps = permutations (m); unsigned r = kd.n_crossings; for (unsigned i = 1; i <= ps.size (); i ++) { @@ -2362,6 +2455,7 @@ compute_splitting_bounds () } printf (" r = %d\n", r); + assert (b_lk_weak <= r); assert (b <= r); // non-trivial link, sp at least 1. @@ -2383,12 +2477,10 @@ compute_splitting_bounds () printf (" > sp = %d (b + b_lk_weak)\n", b); else printf (" > %d <= sp <= %d (b + b_lk_weak)\n", b, r); - } else if (b_lk_weak == r) { assert (b < b_lk_weak); - printf (" > sp = %d (b_lk_weak)\n", b_lk_weak); } } diff --git a/mpimain.cpp b/mpimain.cpp index fec8ddd..bff047b 100644 --- a/mpimain.cpp +++ b/mpimain.cpp @@ -14,10 +14,10 @@ master () { basedvector work; - for (unsigned i = 1; i <= 14; i ++) - for (unsigned j = 1; j <= mt_links (i, 0); j ++) + for (unsigned i = 1; i <= 10; i ++) + for (unsigned j = 1; j <= mt_links (i); j ++) { - knot_diagram kd (mt_links (i, 0, j)); + knot_diagram kd (mt_links (i, j)); unsigned n = kd.num_components (); if (n < 2) continue; @@ -116,6 +116,7 @@ file_exists (const char *file) return 1; } +#if 0 void compute_forgetful (int rank, knot_desc desc, const char *buf) { @@ -291,6 +292,215 @@ compute_forgetful (int rank, knot_desc desc, const char *buf) write (w, desc); write (w, pages); } +#endif + +unsigned +compute_b_lk_weak (knot_diagram &kd) +{ + unsigned m = kd.num_components (); + assert (m > 1); + + if (m == 2) + { + unsigned total_lk = kd.total_linking_number (); + return total_lk == 0 ? 2 : total_lk; + } + + 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 (m == u.num_sets ()); + + map root_comp; + unsigned t = 0; + for (unsigned i = 1; i <= kd.num_edges (); i ++) + { + if (u.find (i) == i) + { + ++ t; + root_comp.push (i, t); + } + } + assert (t == m); + + unsigned b_lk_weak = 0; + + for (unsigned i = 1; i <= m; i ++) + for (unsigned j = i + 1; j <= m; j ++) + { + assert (i < j); + + int lk = 0; + for (unsigned x = 1; x <= kd.n_crossings; x ++) + { + unsigned r1 = root_comp(u.find (kd.ept_edge (kd.crossings[x][1]))), + r2 = root_comp(u.find (kd.ept_edge (kd.crossings[x][2]))); + if (((r1 == i) && (r2 == j)) + || ((r2 == i) && (r1 == j))) + { + if (kd.is_to_ept (kd.crossings[x][1]) == kd.is_to_ept (kd.crossings[x][4])) + lk ++; + else + lk --; + } + } + assert (is_even (lk)); + lk /= 2; + + if (lk == 0) + { + smallbitset ci (m); + ci.push (i); + + smallbitset cj (m); + cj.push (j); + + smallbitset c (m); + c.push (i); + c.push (j); + knot_diagram Lij (SUBLINK, c, kd); + + multivariate_laurentpoly P_Lij = Kh_poincare_polynomial (Lij); + + knot_diagram Li_join_Lj (DISJOINT_UNION, + knot_diagram (SUBLINK, ci, kd), + knot_diagram (SUBLINK, cj, kd)); + + multivariate_laurentpoly P_Li_join_Lj = Kh_poincare_polynomial (Li_join_Lj); + + if (P_Lij != P_Li_join_Lj) + lk = 2; // non-split + } + + b_lk_weak += abs (lk); + } + + return b_lk_weak == 0 ? 2 : b_lk_weak; +} + +void +compute_splitting_bounds (knot_diagram &kd) +{ + int rank = self_rank (); + + typedef fraction_field > Z2x; + + unsigned m = kd.num_components (); + assert (m > 1); + + printf ("[% 2d] ", rank); show (kd); newline (); + printf ("[% 2d] m = %d\n", rank, m); + + 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 () == m); + + map root_comp; + unsigned t = 0; + for (unsigned i = 1; i <= kd.num_edges (); i ++) + { + if (u.find (i) == i) + { + ++ t; + root_comp.push (i, t); + } + } + assert (t == m); + + basedvector comp_weightQ (m); + for (unsigned i = 1; i <= m; i ++) + comp_weightQ[i] = Q (i); + unsigned bQ = splitting_bound (kd, comp_weightQ); + + basedvector comp_weightZ2x (m); + for (unsigned i = 1; i <= m; i ++) + comp_weightZ2x[i] = Z2x (polynomial (Z2 (1), i)); + unsigned bZ2x = splitting_bound (kd, comp_weightZ2x); + + // lower bound + unsigned b = std::max (bQ, bZ2x); + + printf ("[% 2d] bQ = %d\n", rank, bQ); + printf ("[% 2d] bZ2x = %d\n", rank, bZ2x); + printf ("[% 2d] b = %d\n", rank, b); + + + unsigned total_lk = kd.total_linking_number (); + unsigned b_lk_weaker = total_lk == 0 ? 2 : total_lk; + + unsigned b_lk_weak = compute_b_lk_weak (kd); + assert (b_lk_weaker <= b_lk_weak); + + printf ("[% 2d] b_lk_weaker = %d\n", rank, b_lk_weaker); + printf ("[% 2d] b_lk_weak = %d\n", rank, b_lk_weak); + + if (b_lk_weaker < b_lk_weak) + printf ("[% 2d] > STRICTLY WEAKER\n", rank); + + basedvector, 1> ps = permutations (m); + unsigned r = kd.n_crossings; + for (unsigned i = 1; i <= ps.size (); i ++) + { + basedvector p = ps[i]; + + unsigned ri = 0; + for (unsigned j = 1; j <= kd.n_crossings; j ++) + { + unsigned upper_e = kd.ept_edge (kd.crossings[j][2]), + lower_e = kd.ept_edge (kd.crossings[j][1]); + + unsigned upper_c = root_comp(u.find (upper_e)), + lower_c = root_comp(u.find (lower_e)); + + if (upper_c != lower_c + && p[upper_c] < p[lower_c]) + ri ++; + } + + if (ri < r) + r = ri; + } + printf ("[% 2d] r = %d\n", rank, r); + + assert (b_lk_weak <= r); + assert (b <= r); + + // non-trivial link, sp at least 1. + unsigned best = std::max (b, b_lk_weak); + + if (best == r) + printf ("[% 2d] > sp = %d", rank, r); + else + printf ("[% 2d] > %d <= sp <= %d", rank, best, r); + + printf (" "); + + if (b == best + && b_lk_weak == best) + printf ("(b + b_lk_weak)"); + else if (b == best) + printf ("(b)"); + else + { + assert (b_lk_weak == best); + printf ("(b_lk_weak)"); + } + + fflush (stdout); +} void slave () @@ -311,15 +521,8 @@ slave () printf ("[% 2d] CMD_DO %s\n", rank, desc.name ().c_str ()); - assert (desc.t == knot_desc::MT); - char buf[1000]; - sprintf (buf, "/scratch/network/cseed/forgetful/L%d_%d.dat.gz", - desc.i, desc.j); - - if (! file_exits ()) - compute_forgetful (rank, desc, buf); - else - printf ("skip %s: exists.\n", buf); + knot_diagram kd = desc.diagram (); + compute_splitting_bounds (kd); send_int (0, 0); }