diff --git a/kk.cpp b/kk.cpp index 9d3842e..9a1b634 100644 --- a/kk.cpp +++ b/kk.cpp @@ -2,14 +2,10 @@ #include #include #include -#include -#include #include #include #include -const unsigned max_threads = 4; - const char *program_name; void @@ -91,11 +87,11 @@ void tex_footer () const char *knot = 0; const char *invariant = 0; const char *field = "Z2"; -std::string periodicity_test = "Przytycki"; -int period = 5; knot_diagram kd; bool reduced = 0; -std::string in_file_name = "/home/wojtek/ownCloud/Lokalny/khovanov-homology-computation/both.txt"; + +extern int period; +extern std::string periodicity_test; class hg_grading_mapper { @@ -334,170 +330,6 @@ int compute_s_inv(knot_diagram& kd) { return qmin + 1; } -std::pair parse_data_from_file(const std::string& data) { - auto knot_name_stop = data.find(" "); - auto p2 = data.find("=") + 2; - std::string knot_name = data.substr(0, knot_name_stop); - int period = std::stoi(data.substr(knot_name_stop + 3)); - return make_pair(knot_name, period); -} - -std::string perform_computations(const std::string& knot_name, - knot_diagram kd, - std::vector periods) { - std::ostringstream res; - Kh_periodicity_checker Kh_pc(kd, knot_name); - for(auto p: periods) { - res << "Kh criterion: " << Kh_pc(p) << std::endl; - } - return res.str(); -} - -void check_periodicity(std::string out_file) { - if(periodicity_test == "all") { - Kh_periodicity_checker Kh_pc(kd, std::string(knot)); - for(auto& p : primes_list) { - std::cout << "Kh criterion: " - << Kh_pc(p) << std::endl; - } - } - else if(periodicity_test == "Kh_from_file") { - std::ifstream in_file(in_file_name); - if(!in_file) { - std::cerr << "Cannot open file " << in_file_name << "\n"; - exit(EXIT_FAILURE); - } - unsigned num_threads = std::min(max_threads, std::thread::hardware_concurrency()); - unsigned i = 0; - std::string line, previous_knot; - knot_diagram kd_temp; - std::vector> v_future(num_threads); - std::vector periods; - while(std::getline(in_file, line)) { - if(line == "") continue; - std::string knot_name; - int period; - tie(knot_name, period) = parse_data_from_file(line); - if(knot_name == previous_knot) { - auto p = find(primes_list.begin(), primes_list.end(), period); - if(p != primes_list.end()) { - periods.push_back(period); - } - else { - std::cerr << "Period " << period << " cannot be checked..." << "\n"; - } - } - else { - if(i == num_threads) { - for(auto& v_f : v_future) - std::cout << v_f.get(); - i = 0; - } - if(previous_knot.size() > 0) { - std::cerr << "Checking " << previous_knot << "\n"; - v_future[i] = std::async(perform_computations, previous_knot, kd_temp, periods); - ++i; - periods.clear(); - } - kd_temp = parse_knot(knot_name.c_str()); - kd_temp.marked_edge = 1; - periods.push_back(period); - previous_knot = knot_name; - } - } - for(auto& v_f : v_future) { - if(v_f.valid()) - std::cout << v_f.get(); - } - } - else if(periodicity_test == "all_seq") { - std::string k(knot); - // first check whether the number of crossings is bigger or lower than 10 - if(isdigit(k[1])) { - // at least 10 crossings - if(k[1] == '0') { - // ten crossings - int num_cr = 10; - int knot_index = stoi(k.substr(3)); - for(unsigned i = knot_index; i < rolfsen_crossing_knots(num_cr); i++) { - std::string knot_name = std::to_string(num_cr) + "_" + std::to_string(i); - knot_diagram kd_temp = parse_knot(knot_name.c_str()); - kd.marked_edge = 1; - Kh_periodicity_checker Kh_pc(kd_temp, knot_name); - for(auto& p : primes_list) { - std::cout << "Kh criterion: " - << Kh_pc(p) << std::endl; - } - } - } - else { - int num_cr = stoi(k.substr(0,2)); - int knot_index = stoi(k.substr(3)); - char alt = k[2]; - bool alternating = (alt == 'a' ? true : false); - for(unsigned i = knot_index; i <= htw_knots(num_cr, alternating); i++) { - std::string knot_name = std::to_string(num_cr) + alt + std::to_string(i); - knot_diagram kd_temp = parse_knot(knot_name.c_str()); - kd.marked_edge = 1; - Kh_periodicity_checker Kh_pc(kd_temp, knot_name); - for(auto& p : primes_list) { - std::cout << "Kh criterion: " - << Kh_pc(p) << std::endl; - } - } - } - } - else { - // at most nine crossings - int num_cr = stoi(k.substr(0, 1)); - int knot_index = stoi(k.substr(2)); - for(unsigned i = knot_index; i <= rolfsen_crossing_knots(num_cr); i++) { - std::string knot_name = std::to_string(num_cr) + "_" + std::to_string(i); - knot_diagram kd_temp = parse_knot(knot_name.c_str()); - kd.marked_edge = 1; - Kh_periodicity_checker Kh_pc(kd_temp, knot_name); - for(auto& p : primes_list) { - std::cout << "Kh criterion: " - << Kh_pc(p) << std::endl; - } - } - } - } - else { - if(period == 2 || period == 3) { - std::cout << "Sorry, the criterion doesn't work for period " - << period << "...\n"; - exit(EXIT_FAILURE); - } - auto result = std::find(primes_list.begin(), primes_list.end(), period); - if(result == primes_list.end()) { - std::cout << "For now you can only check periodicity for primes up to 19..." << "\n"; - exit(EXIT_FAILURE); - } - std::ofstream out(out_file, std::ios_base::app); - - if(periodicity_test == "Przytycki") { - Przytycki_periodicity_checker P_pc(compute_jones(kd)); - if(out_file.size() != 0) - out << P_pc(period) << std::endl; - else - std::cout << P_pc(period) << std::endl; - } - else if(periodicity_test == "Kh") { - Kh_periodicity_checker Kh_pc(kd, std::string(knot)); - if(out_file.size() != 0) - out << Kh_pc(period) << std::endl; - else - std::cout << Kh_pc(period) << std::endl; - } - else { - std::cout << "Sorry, I don't recognize this option..." << "\n"; - exit(EXIT_FAILURE); - } - } -} - - template void compute_invariant () { @@ -579,58 +411,56 @@ compute_invariant () ss.texshow (outfp, mapper); tex_footer (); } - else if (!strcmp (invariant, "leess")) - { - cube c (kd, reduced); - ptr > C = c.khC; + else if (!strcmp (invariant, "leess")) { + cube c (kd, reduced); + 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); + 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); + + unsigned m = kd.num_components (); + hg_grading_mapper mapper (m); - unsigned m = kd.num_components (); - hg_grading_mapper mapper (m); + sseq_bounds b (C, mapper); + basedvector pages; - sseq_bounds b (C, mapper); - basedvector pages; + int k = 0; + for (;;) { + chain_complex_simplifier s (C, d, + maybe (1), maybe (2*k)); + C = s.new_C; + d = s.new_d; + k ++; - int k = 0; - for (;;) - { - chain_complex_simplifier s (C, d, - maybe (1), maybe (2*k)); - C = s.new_C; - d = s.new_d; - k ++; - - grading dk_gr (1, 2*k); - pages.append (sseq_page (b, k, dk_gr, d.graded_piece (dk_gr), mapper)); - if (d == 0) - break; - } - - sseq ss (b, pages); - - tex_header (); - fprintf (outfp, "$E_k = %s^{BN}_k(\\verb~%s~; \\verb~%s~)$:\\\\\n", - (reduced - ? "\\widetilde{E}" - : "E"), - knot, field); - ss.texshow (outfp, mapper); - tex_footer (); + grading dk_gr (1, 2*k); + pages.append (sseq_page (b, k, dk_gr, d.graded_piece (dk_gr), mapper)); + if (d == 0) + break; } + + sseq ss (b, pages); + + tex_header (); + fprintf (outfp, "$E_k = %s^{BN}_k(\\verb~%s~; \\verb~%s~)$:\\\\\n", + (reduced + ? "\\widetilde{E}" + : "E"), + knot, field); + ss.texshow (outfp, mapper); + tex_footer (); + } else if (!strcmp (invariant, "s")) { int s = compute_s_inv(kd); fprintf (outfp, "s(%s; %s) = %d\n", knot, field, s); } - else - { - fprintf (stderr, "error: unknown invariant %s\n", invariant); - exit (EXIT_FAILURE); - } + else { + fprintf (stderr, "error: unknown invariant %s\n", invariant); + exit (EXIT_FAILURE); + } } void @@ -834,14 +664,6 @@ main (int argc, char **argv) } periodicity_test = argv[i]; } - else if(!strcmp(argv[i], "-i")) { - i++; - if(i == argc) { - fprintf (stderr, "error: missing argument to option `-t'\n"); - exit (EXIT_FAILURE); - } - in_file_name = argv[i]; - } else { fprintf (stderr, "error: unknown argument `%s'\n", argv[1]); fprintf (stderr, " use -h for usage\n"); @@ -883,48 +705,41 @@ main (int argc, char **argv) kd = parse_knot (knot); kd.marked_edge = 1; - if (!strcmp (invariant, "gauss")) - { + if (!strcmp (invariant, "gauss")) { basedvector, 1> gc = kd.as_gauss_code (); - for (unsigned i = 1; i <= gc.size (); i ++) - { - if (i > 1) - printf (":"); - for (unsigned j = 1; j <= gc[i].size (); j ++) - { - if (j > 1) - printf (","); - printf ("%d", gc[i][j]); - } - } - newline (); - } + for (unsigned i = 1; i <= gc.size (); i ++) { + if (i > 1) + printf (":"); + for (unsigned j = 1; j <= gc[i].size (); j ++) { + if (j > 1) + printf (","); + printf ("%d", gc[i][j]); + } + } + newline (); + } - if (!strcmp (invariant, "sq2")) - { - if (strcmp (field, "Z2")) - { - fprintf (stderr, "warning: sq2 only defined over Z2, ignoring -f %s\n", field); - field = "Z2"; - } - - compute_sq2 (); + if (!strcmp (invariant, "sq2")) { + if (strcmp (field, "Z2")) { + fprintf (stderr, "warning: sq2 only defined over Z2, ignoring -f %s\n", field); + field = "Z2"; } - else if (!strcmp (invariant, "gss")) - { - if (strcmp (field, "Z2")) - { - fprintf (stderr, "warning: gss only defined over Z2, ignoring -f %s\n", field); - field = "Z2"; - } - compute_gss (); + compute_sq2 (); + } + else if (!strcmp (invariant, "gss")) { + if (strcmp (field, "Z2")) { + fprintf (stderr, "warning: gss only defined over Z2, ignoring -f %s\n", field); + field = "Z2"; } + + compute_gss (); + } else if(!strcmp(invariant, "jones")) { std::cout << "Jones polynomial of " << knot << " = " << compute_jones(kd, reduced) << "\n"; } else if(!strcmp(invariant, "periodicity")) { - check_periodicity((file ? std::string(file) : std::string())); + check_periodicity(kd, std::string(knot), period, std::string(field)); } else if(!strcmp(invariant, "khp")) { multivariate_laurentpoly khp; @@ -947,20 +762,18 @@ main (int argc, char **argv) << ") of " << knot << " = " << std::endl << khp << std::endl; } - else - { - if (!strcmp (field, "Z2")) - compute_invariant (); - else if (!strcmp (field, "Z3")) - compute_invariant > (); - else if (!strcmp (field, "Q")) - compute_invariant (); - else - { - fprintf (stderr, "error: unknown field %s\n", field); - exit (EXIT_FAILURE); - } + else { + if (!strcmp (field, "Z2")) + compute_invariant (); + else if (!strcmp (field, "Z3")) + compute_invariant> (); + else if (!strcmp (field, "Q")) + compute_invariant (); + else { + fprintf (stderr, "error: unknown field %s\n", field); + exit (EXIT_FAILURE); } + } if (file) fclose (outfp); diff --git a/periodicity.cpp b/periodicity.cpp index c1364eb..0ed9903 100644 --- a/periodicity.cpp +++ b/periodicity.cpp @@ -2,6 +2,12 @@ #include #include #include +#include + +std::string periodicity_test = "Przytycki"; +int period = 5; + +extern multivariate_laurentpoly compute_jones(const knot_diagram& k, bool reduced = false); using polynomial_tuple = std::vector, multivariate_laurentpoly, multivariate_laurentpoly>>; @@ -39,7 +45,7 @@ bool Przytycki_periodicity_checker::check(int period) const { std::string Przytycki_periodicity_checker::operator () (int period) const { std::ostringstream res; - res << knot << ": period = " << period << ": " + res << knot_name << ": period = " << period << ": " << (check(period) ? "Maybe" : "No"); return res.str(); } @@ -82,8 +88,9 @@ multivariate_laurentpoly Kh_bounds_iterator::get_polynomial() const { return p; } +template<> std::vector> -Kh_periodicity_checker::compute_knot_polynomials(knot_diagram& kd) { +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..."; @@ -122,21 +129,86 @@ Kh_periodicity_checker::compute_knot_polynomials(knot_diagram& kd) { std::cerr << "KhP = " << khp << "\n"; std::cerr << "LeeP = " << leep << "\n"; } - // for(unsigned i = 0; i < lee_ss_polynomials.size(); ++i) { - // std::cerr << "lee_ss_polynomials[" << i << "]= " - // << lee_ss_polynomials[i] << "\n"; - // std::cerr << "mul[" << i << "] = " << mul[i] << "\n"; - // } return lee_ss_polynomials; } +template +std::vector> +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::cerr << "Computing Khovanov homology" << std::endl; + std::vector lee_ss_polynomials; + int k = 0; + for(;;) { + chain_complex_simplifier s(C, d, maybe(1), maybe(2*k)); + C = s.new_C; + d = s.new_d; + if(k % 2 == 0) { + lee_ss_polynomials.push_back(C->free_poincare_polynomial()); + if(k != 0) + mul.push_back(polynomial(Z(1)) + polynomial(Z(1), VARIABLE, 1, 1) * polynomial(Z(1), VARIABLE, 2, 2 * k)); + } + if(d == 0) + break; + k++; + } + + khp = *lee_ss_polynomials.begin(); + leep = *lee_ss_polynomials.rbegin(); + + if(verbose) { + std::cerr << "KhP = " << khp << "\n"; + std::cerr << "LeeP = " << leep << "\n"; + } + return lee_ss_polynomials; +} + + +Kh_periodicity_checker::Kh_periodicity_checker(knot_diagram& kd, + std::string knot_n, + std::string f = "Z2") : + knot_name(knot_n), field(f) { + ev_index = 1; + index = 2; + quot = std::vector(); + mul = std::vector(); + if(field == "Z2") + compute_quot(compute_knot_polynomials(kd)); + else if(field == "Z3") + compute_quot(compute_knot_polynomials>(kd)); + else if(field == "Z5") + compute_quot(compute_knot_polynomials>(kd)); + else if(field == "Z7") + compute_quot(compute_knot_polynomials>(kd)); + else if(field == "Z11") + compute_quot(compute_knot_polynomials>(kd)); + else if(field == "Q") + compute_quot(compute_knot_polynomials(kd)); + else { + std::cerr << "Sorry, I don't recognize field " << f << ". Exiting..." << "\n"; + exit(EXIT_FAILURE); + } +} + void Kh_periodicity_checker::compute_quot(const std::vector& lee_ss_polynomials) { - // quot.push_back(polynomial(Z(0))); for(unsigned i = 1; i < lee_ss_polynomials.size(); ++i) { polynomial diff = lee_ss_polynomials[i-1] - lee_ss_polynomials[i]; polynomial q = 0; - // std::cerr << "diff = " << diff << "\n"; - // std::cerr << "mul = " << mul[i-1] << "\n"; while(diff != 0) { pair m = diff.head(); if(m.first.m[1] == 1) { @@ -160,9 +232,6 @@ void Kh_periodicity_checker::compute_quot(const std::vector& lee_ss_ } quot.push_back(q); } - // for(unsigned i = 0; i < quot.size(); ++i) { - // std::cerr << "quot[" << i << "] = " << quot[i] << "\n"; - // } } polynomial_tuple @@ -222,13 +291,9 @@ Kh_periodicity_checker::compute_bounds(const polynomial_tuple& p_tuple, int peri mon *= monomial(VARIABLE, j.key(), v); } } - // std::cerr << polynomial(i.val() * pow(-1,exp), mon) << "\n"; Z v_temp = i.val() * pow(-1, exp); polynomial p_temp = (polynomial(1, mon) * mul).evaluate(-1, ev_index); p_temp = pcc.reduce(p_temp - invert_variable(p_temp, index)); - // std::cerr << "p_temp = " << p_temp << "\n"; - // std::cerr << "v_temp = " << v_temp << "\n"; - // std::cerr << "min_exp = " << min_exp << "\n"; if(bounds_v.count(p_temp)) { if(v_temp >= 0) bounds_v[p_temp].second += (v_temp * period); @@ -259,7 +324,8 @@ Kh_periodicity_checker::compute_bounds(const polynomial_tuple& p_tuple, int peri return bounds_v; } -Test_Result Kh_periodicity_checker::check(const polynomial_tuple& polynomials, +Kh_periodicity_checker::Test_Result +Kh_periodicity_checker::check(const polynomial_tuple& polynomials, int period) const { periodic_congruence_checker pcc(period); polynomial t = polynomial(COPY, leep); @@ -299,8 +365,23 @@ Test_Result Kh_periodicity_checker::check(const polynomial_tuple& polynomials, std::string Kh_periodicity_checker::operator () (int period) const { std::ostringstream out; + if(field == "Z5" && Zp<5>(period) == Zp<5>(0)) + return "Period (" + std::to_string(period) + + ") has to be relatively prime to " + + "the characteristic of the field (" + + field + ")..."; + else if(field == "Z7" && Zp<7>(period) == Zp<7>(0)) + return "Period (" + std::to_string(period) + + ") has to be relatively prime to " + + "the characteristic of the field (" + + field + ")..."; + else if(field == "Z11" && Zp<11>(period) == Zp<11>(0)) + return "Period (" + std::to_string(period) + + ") has to be relatively prime to " + + "the characteristic of the field (" + + field + ")..."; // first check Przytycki's criterion - Przytycki_periodicity_checker P_pc(evaluate_with_copy(khp, -1, ev_index)); + Przytycki_periodicity_checker P_pc(evaluate_with_copy(khp, -1, ev_index), knot_name); if(!P_pc.check(period)) { out << knot_name << ": period = " << period << ": No (Przytycki's criterion)."; } @@ -309,7 +390,42 @@ std::string Kh_periodicity_checker::operator () (int period) const { Test_Result res = check(q_r, period); out << knot_name << ": period = " << period << ": " << (res == Test_Result::MAYBE ? "Maybe" : - (res == Test_Result::NO ? "No" : "No (Nontrivial decomposition).")); + (res == Test_Result::NO ? "No" : "No (Nontrivial decomposition) (" + + field + ")")); } return out.str(); } + +void check_periodicity(knot_diagram& kd, const std::string knot_name, int period, std::string field) { + if(periodicity_test == "all") { + Kh_periodicity_checker Kh_pc(kd, knot_name, field); + for(auto& p : primes_list) { + std::cout << "Kh criterion: " + << Kh_pc(p) << std::endl; + } + } + else { + if(period == 2 || period == 3) { + std::cout << "Sorry, the criterion doesn't work for period " + << period << "...\n"; + exit(EXIT_FAILURE); + } + auto result = std::find(primes_list.begin(), primes_list.end(), period); + if(result == primes_list.end()) { + std::cout << "For now you can only check periodicity for primes up to 19..." << "\n"; + exit(EXIT_FAILURE); + } + if(periodicity_test == "Przytycki") { + Przytycki_periodicity_checker P_pc(compute_jones(kd), knot_name); + std::cout << P_pc(period) << std::endl; + } + else if(periodicity_test == "Kh") { + Kh_periodicity_checker Kh_pc(kd, std::string(knot_name), field); + std::cout << Kh_pc(period) << std::endl; + } + else { + std::cout << "Sorry, I don't recognize this option..." << "\n"; + exit(EXIT_FAILURE); + } + } +} diff --git a/periodicity.h b/periodicity.h index 6119fea..800d193 100644 --- a/periodicity.h +++ b/periodicity.h @@ -9,16 +9,11 @@ #include extern bool verbose; -extern const char* knot; -extern std::string periodicity_test; +constexpr std::array primes_list = {5, 7, 11, 13, 17, 19}; -const std::vector primes_list = {5, 7, 11, 13, 17, 19}; - -enum class Test_Result { MAYBE, NO, NO_NONTRIVIAL_DECOMP }; - -const unsigned eval_index = 1; -const unsigned invert_index = 2; +constexpr unsigned eval_index = 1; +constexpr unsigned invert_index = 2; template class periodic_congruence_checker { @@ -35,9 +30,9 @@ protected: } public: - periodic_congruence_checker(int pprime = 5, + periodic_congruence_checker(int p = 5, unsigned ind = invert_index) : - prime(pprime), + prime(p), index(ind) {} @@ -47,7 +42,6 @@ public: bool operator() (const polynomial& pol) const { return reduce(prepare_polynomial(pol)) == 0; - // return reduce(prepare_polynomial(pol)) == 0; } }; @@ -62,8 +56,6 @@ periodic_congruence_checker::reduce(const multivariate_laurentpoly& pol) c monomial mon = monomial(VARIABLE, index, c); res += polynomial(i.val(), mon); } - // if(verbose) - // std::cout << "res = " << res << "\n"; return res; } @@ -72,9 +64,11 @@ class Przytycki_periodicity_checker { using monomial = multivariate_laurent_monomial; polynomial jones_pol; + std::string knot_name; public: - Przytycki_periodicity_checker(polynomial j) : jones_pol(j) {} + Przytycki_periodicity_checker(polynomial j, std::string knot_n) : + jones_pol(j), knot_name(knot_n) {} ~Przytycki_periodicity_checker() {} @@ -117,11 +111,15 @@ class Kh_periodicity_checker { unsigned ev_index; unsigned index; + enum class Test_Result { MAYBE, NO, NO_NONTRIVIAL_DECOMP }; + polynomial khp, leep; std::vector quot, mul, quotients, remainders; std::string knot_name; + std::string field; + template std::vector compute_knot_polynomials(knot_diagram& kd); void compute_quot(const std::vector& lee_ss_polynomials); polynomial_tuple @@ -131,14 +129,7 @@ class Kh_periodicity_checker { Test_Result check(const polynomial_tuple& polynomials, int period) const; public: - Kh_periodicity_checker(knot_diagram& kd, std::string knot_n) : - knot_name(knot_n) { - ev_index = 1; - index = 2; - quot = std::vector(); - mul = std::vector(); - compute_quot(compute_knot_polynomials(kd)); - } + Kh_periodicity_checker(knot_diagram& kd, std::string knot_n, std::string f); ~Kh_periodicity_checker() {} @@ -153,4 +144,7 @@ class Kh_periodicity_checker { } }; +void check_periodicity(knot_diagram& kd, const std::string knot_name, + int period = 5, const std::string field = "Z2"); + #endif // _KNOTKIT_PERIODICITY_H