#include #include bool Przytycki_periodicity_checker::check(int period) const { switch(period) { case 5: { periodic_congruence_checker> pcc(5); return pcc(jones_pol); } case 7: { periodic_congruence_checker> pcc(7); return pcc(jones_pol); } case 11: { periodic_congruence_checker> pcc(11); return pcc(jones_pol); } case 13: { periodic_congruence_checker> pcc(13); return pcc(jones_pol); } case 17: { periodic_congruence_checker> pcc(17); return pcc(jones_pol); } case 19: { periodic_congruence_checker> pcc(19); return pcc(jones_pol); } } } std::string Przytycki_periodicity_checker::operator () (int period) const { std::ostringstream res; res << knot << ": period = " << period << ": " << (check(period) ? "Maybe" : "No"); return res.str(); } template polynomial_iterator::polynomial_iterator(const multivariate_laurentpoly& pol, start_pos sp) { for(typename map::const_iter i = pol.coeffs; i; ++i) { monomials.push_back(i.key()); bounds.push_back(i.val()); current_pos.push_back(Z(0)); } if(sp == start_pos::begin) { level = 0; } else { level = bounds.size(); } #ifndef NDEBUG check_current_pos(); #endif } #ifndef NDEBUG template void polynomial_iterator::check_current_pos() { assert(bounds.size() == monomials.size()); assert(bounds.size() == current_pos.size()); assert(level <= current_pos.size()); for(unsigned i = 0; i < current_pos.size(); i++) { if(i < level) { assert((current_pos[i] <= bounds[i]) && Z(0) <= (current_pos[i])); } else if(i == level) { if(level > 0) assert(current_pos[i] <= bounds[i] && Z(0) < current_pos[i]); else assert((current_pos[i] <= bounds[i]) && Z(0) <= (current_pos[i])); } else assert(current_pos[i] == Z(0)); } } #endif // NDEBUG template polynomial_iterator& polynomial_iterator::operator ++ () { #ifndef NDEBUG check_current_pos(); #endif if(level == monomials.size()) return *this; unsigned i = 0; while(i <= level) { #ifndef NDEBUG check_current_pos(); #endif if(current_pos[i] < bounds[i]) { current_pos[i] += 1; break; } else { if(i == level) { if(level < monomials.size() - 1) { current_pos[i] = 0; current_pos[i+1] += 1; level++; break; } else { level++; break; } } else { current_pos[i] = 0; } } i++; } return *this; } template multivariate_laurentpoly polynomial_iterator::operator *() const { polynomial res; for(unsigned i = 0; i <= level; i++) { res += polynomial(current_pos[i], monomials[i]); } return res; } template std::string polynomial_iterator::write_self() const { std::ostringstream res; res << "level = " << level << std::endl << "monomials:" << std::endl; for(auto& mon : monomials) res << mon << std::endl; res << "bounds: " << std::endl; for(auto& b : bounds) res << b << std::endl; res << "current_pos: " << std::endl; for(auto& pos : current_pos) res << pos << std::endl; return res.str(); } void Kh_periodicity_checker::compute_knot_polynomials(knot_diagram& kd) { unsigned m = kd.num_components (); if (m != 1) { std::cerr << "warning: this implementation of the criterion works for knots only..."; exit (EXIT_FAILURE); } cube c (kd, 0); ptr > C = c.khC; mod_map d = c.compute_d (1, 0, 0, 0, 0); for (unsigned i = 1; i <= kd.n_crossings; i ++) d = d + c.H_i (i); assert (d.compose (d) == 0); // computing Khovanov homology if(verbose) std::cout << "Computing Khovanov homology" << std::endl; { chain_complex_simplifier s (C, d, maybe(1), maybe(0)); C = s.new_C; d = s.new_d; khp = C->free_poincare_polynomial(); if(verbose) std::cout << "KhP = " << khp << "\n"; } // computing Lee homolgy if(verbose) std::cout << "Computing Lee homology" << std::endl; { chain_complex_simplifier s(C, d, maybe(1), maybe(2)); C = s.new_C; d = s.new_d; leep = C->free_poincare_polynomial(); if(d != 0) { std::cout << "For now, you can only use this criterion on Kh-thin knots." << std::endl; exit(EXIT_FAILURE); } if(verbose) { std::cout << "LeeP = " << leep << "\n"; } } } void Kh_periodicity_checker::compute_quot() { polynomial diff = khp - leep; while(diff != 0) { pair m = diff.head(); if(m.first.m[1] == 1) { pair m1 = diff.tail(); while(m1.first.m.card() == 1 && m1.first.m[2]) { quot += polynomial(m1.second, m1.first); polynomial p = polynomial(m1.second, m1.first) * mul; diff -= p; if(diff != 0) m1 = diff.tail(); else break; } if(diff != 0) m = diff.head(); else break; } quot += polynomial(m.second, m.first); polynomial p = polynomial(m.second, m.first) * mul; diff -= p; } } std::pair, multivariate_laurentpoly> Kh_periodicity_checker::compute_quotient_and_remainder(const polynomial& quot, int period) const { polynomial quotient, remainder; for(map::const_iter i = quot.coeffs; i; i++) { std::tuple div = i.val().divide_with_remainder(period - 1); quotient += polynomial(std::get<0>(div), i.key()); remainder += polynomial(std::get<1>(div), i.key()); } if(verbose) { std::cout << "Decomposition of Khp = " << std::endl << leep << " + (" << mul << ") * (" << remainder; if(quotient != 0) { std::cout << " + " << (period - 1) << " * (" << quotient << ")"; } std::cout << ")" << std::endl; } return std::make_pair(quotient, remainder); } bool Kh_periodicity_checker::check(const polynomial& q, const polynomial& r, int period) const { periodic_congruence_checker pcc(period); polynomial t = leep + mul * r; if(q == 0) { return pcc(t.evaluate(-1,1)); } if(verbose) std::cout << "Checking congruences..."; polynomial_iterator pi(q); polynomial_iterator pi_end(q, polynomial_iterator::start_pos::end); Z count = pi.get_count(); if(verbose) std::cout << count << " candidates..." << std::endl; Z step = 1; if(count >= 32) step = count / 32; Z c = 0; while(pi != pi_end) { //std::cout << "pi: " << std::endl << pi; polynomial temp = t + polynomial(period - 1) * mul * (*pi); if(pcc(temp.evaluate(-1,1))) { std::cout << "Candidates:" << std::endl << "EKhP_1 = " << temp << std::endl << "EKhP_" << (period - 1) << " = " << (polynomial(period - 1) * mul *(r - *pi)) << std::endl; return true; } ++pi; c += 1; if(verbose && c % step == 0) std::cout << c << "/" << count << "..." << std::endl; } return false; } std::string Kh_periodicity_checker::operator () (int period) const { std::ostringstream out; std::pair q_r = compute_quotient_and_remainder(quot, period); bool res = check(std::get<0>(q_r), std::get<1>(q_r), period); out << knot << ": period = " << period << ": " << (res ? "Maybe" : "No"); return out.str(); }