Strengthened b'_lk to use Khovanov homology. Set up to compute sp

bounds in paralllel.
This commit is contained in:
Cotton Seed 2013-01-17 18:43:52 -05:00
parent e19a274c8e
commit f3d7e22f51
4 changed files with 382 additions and 29 deletions

View File

@ -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<unsigned, 1> (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<unsigned, 1> (num_epts ());
ept_index = basedvector<unsigned, 1> (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),

View File

@ -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<basedvector<unsigned, 1>, 1> &crossings_);

126
main.cpp
View File

@ -2262,6 +2262,106 @@ permutations (unsigned n)
return permutations (v);
}
template<class R> multivariate_laurentpoly<Z>
Kh_poincare_polynomial (knot_diagram &kd)
{
cube<R> c (kd);
mod_map<R> d = c.compute_d (1, 0, 0, 0, 0);
chain_complex_simplifier<R> 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<unsigned, unsigned> 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<Z> P_Lij = Kh_poincare_polynomial<Z2> (Lij);
knot_diagram Li_join_Lj (DISJOINT_UNION,
knot_diagram (SUBLINK, ci, kd),
knot_diagram (SUBLINK, cj, kd));
multivariate_laurentpoly<Z> P_Li_join_Lj = Kh_poincare_polynomial<Z2> (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<basedvector<unsigned, 1>, 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<unsigned, 1> 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<basedvector<unsigned, 1>, 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);
}
}

View File

@ -14,10 +14,10 @@ master ()
{
basedvector<knot_desc, 1> 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<unsigned, unsigned> 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<Z> P_Lij = Kh_poincare_polynomial<Z2> (Lij);
knot_diagram Li_join_Lj (DISJOINT_UNION,
knot_diagram (SUBLINK, ci, kd),
knot_diagram (SUBLINK, cj, kd));
multivariate_laurentpoly<Z> P_Li_join_Lj = Kh_poincare_polynomial<Z2> (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<polynomial<Z2> > 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<unsigned, unsigned> 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<Q, 1> comp_weightQ (m);
for (unsigned i = 1; i <= m; i ++)
comp_weightQ[i] = Q (i);
unsigned bQ = splitting_bound<Q> (kd, comp_weightQ);
basedvector<Z2x, 1> comp_weightZ2x (m);
for (unsigned i = 1; i <= m; i ++)
comp_weightZ2x[i] = Z2x (polynomial<Z2> (Z2 (1), i));
unsigned bZ2x = splitting_bound<Z2x> (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<basedvector<unsigned, 1>, 1> ps = permutations (m);
unsigned r = kd.n_crossings;
for (unsigned i = 1; i <= ps.size (); i ++)
{
basedvector<unsigned, 1> 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);
}