knotkit/periodicity.cpp
2016-11-19 22:38:34 +01:00

170 lines
5.2 KiB
C++

#include <periodicity.h>
using polynomial = multivariate_laurentpoly;
using monomial = multivariate_laurent_monomial;
template<class T>
bool congruence_checker::reduce(const polynomial<T>& pol) const {
polynomial res;
for(typename map<monomial, T>::const_iter i = p.coeffs; i; i++) {
int c = i.key().m[index] % (2 * prime);
if(c < 0)
c += (2 * prime);
monomial mon = monomial(VARIABLE, index, c);
res += polynomial(i.val(), mon);
}
if(verbose)
std::cout << "res = " << res << "\n";
return res == 0;
}
polynomial<Z> periodicity_checker::divide(const polynomial<Z> kh,
const polynomial<Z> lee) const {
polynomial <Z> diff = kh - lee;
polynomial <Z> quotient;
while(diff != 0) {
pair<monomial, Z> m = diff.head();
if(m.first.m[1] == 1) {
pair<monomial, Z> m1 = diff.tail();
while(m1.first.m.card() == 1 && m1.first.m[2]) {
quotient += polynomial(m1.second, m1.first);
polynomial p = polynomial(m1.second, m1.first) * mul;
diff -= p;
m1 = diff.tail();
}
}
quotient += polynomial(m.second, m.first);
polynomial p = polynomial(m.second, m.first) * mul;
diff -= p;
}
if(verbose) {
std::cout << "Decomposition of the Khovanov polynomial = "
<< lee << " + ("
<< mul << ") * ("
<< quotient << ")\n";
}
return quotient;
}
std::pair<polynomial<Z>, polynomial<Z>>
periodicity_checker::divide_p(const polynomial& q) const {
polynomial quotient, remainder = 0;
for(map<monomial, Z>::iter i = q.coeffs; i; i++) {
std::tuple<Z,Z> div = i.val().divide_with_remainder(prime - 1);
quotient += polynomial(std::get<0>(div), i.key());
remainder += polynomial(std::get<1>(div), i.key());
}
return std::make_pair(quotient, remainder);
}
////// Functions that verify periodicity of knots and links
void periodicity_congruence(const multivariate_laurentpoly<Z>& lee,
const multivariate_laurentpoly<Z>& remainder,
const multivariate_laurentpoly<Z>& quotient,
int prime) {
using polynomial = multivariate_laurentpoly<Z>;
using monomial = multivariate_laurent_monomial;
// prepare polynomials
polynomial m = (polynomial(1) + polynomial(1, VARIABLE, 1) * polynomial(1, VARIABLE, 2, 2));
polynomial r = lee + m * (remainder - quotient);
// first check if quotient is zero
if(quotient == 0) {
// only one case to check
if(verbose)
std::cout << "All coefficients of the quotient "
"are smaller than "
<< (prime -1) << "...\n";
if(check_congruence((r - invert_variable(r,2)).evaluate(-1,1), prime))
std::cout << knot << " may be " << prime << "-periodic...\n";
else
std::cout << knot << " is not " << prime << "-periodic..." << "\n";
}
// quotient not zero
else {
if(verbose)
std::cout << "Decomposition of the quotient:" << "\n"
<< remainder << " + "
<< (prime - 1) << " * ("
<< quotient << ")\n";
//generate and check all cases
std::vector<std::pair<monomial,Z>> v;
Z number_of_cases = 1;
for(map<monomial,Z>::const_iter i = quotient.coeffs; i; i++) {
v.push_back(std::make_pair(i.key(), i.val()));
number_of_cases *= (i.val() + 1);
// std::cout << i.val() << "\n";
}
if(verbose) {
std::cout << "There are "
<< number_of_cases
<< " cases to check...\n";
}
Z counter = 0;
Z candidates = 0;
// std::cout << "v.size() = " << v.size() << "\n";
for(Z level = 0; level < v.size(); level += 1) {
polynomial pol_temp = m * polynomial(prime, std::get<0>(v[level.get_ui()]));
// std::cout << "level = " << level << " / "
// << (v.size() - 1) << "\n";
int i = 0;
if(level != Z(0))
i++;
for( ; Z(i) < std::get<1>(v[level.get_ui()]) + 1; i++) {
// std::cout << "i = " << i << " / "
// << std::get<1>(v[level.get_ui()]) << "\n";
polynomial p = r + polynomial(i) * pol_temp;
if(level == 0) {
if(check_congruence((p - invert_variable(p, 2)).evaluate(-1,1), prime)) {
candidates += 1;
if(verbose)
std::cout << "Found a candidate..." << "\n";
}
counter += 1;
if(verbose) {
std::cout << counter
<< " / "
<< number_of_cases
<< " cases checked...\n";
}
} // level = 0
else {
for(int level2 = 0; Z(level2) < level; level2++) {
// std::cout << "level2 = " << level2 << " / "
// << level << "\n";
Z n_temp = std::get<1>(v[level2]);
polynomial mon_temp = m * polynomial(prime, std::get<0>(v[level2]));
for(int j = 0; Z(j) < n_temp + 1; j++) {
p += pol_temp;
// std::cout << "j = " << j << " / "
// << n_temp << "\n";
if(check_congruence((p - invert_variable(p, 2)).evaluate(-1,1), prime)) {
candidates += 1;
if(verbose) {
std::cout << "Found a candidate..." << "\n";
}
}
counter += 1;
if(verbose)
std::cout << counter
<< " / "
<< number_of_cases
<< " cases checked...\n";
} // loop over j
} // loop over level2
} // level not zero
} // loop over i
} // loop over level
if(candidates == 0) {
std::cout << knot << " is not "
<< prime << "-periodic...\n";
}
else {
std::cout << knot << " may be "
<< prime << "-periodic,\n"
<< "found " << candidates
<< " decompositions of khp.";
}
}
}