Periodicity congruences
This commit is contained in:
parent
66813d4a15
commit
297e02dc05
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,3 +11,4 @@ GTAGS
|
||||
/parallel.cmd.[eo]*
|
||||
/save
|
||||
*/save
|
||||
/org
|
||||
|
4
Makefile
4
Makefile
@ -11,7 +11,7 @@ CXX = g++ -std=c++11
|
||||
INCLUDES = -I. -I/opt/local/include
|
||||
|
||||
# OPTFLAGS = -g
|
||||
OPTFLAGS = -O2 -g
|
||||
OPTFLAGS = -O2 -g -pg
|
||||
# OPTFLAGS = -O2 -g -DNDEBUG
|
||||
|
||||
LDFLAGS = -L/opt/local/lib
|
||||
@ -55,7 +55,7 @@ all: kk
|
||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||
|
||||
kk: kk.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o kk $^ $(LIBS)
|
||||
$(CXX) $(LDFLAGS) -pg -o kk $^ $(LIBS)
|
||||
|
||||
main: main.o $(COMMON_OBJS)
|
||||
$(CXX) $(LDFLAGS) -o main $^ $(LIBS)
|
||||
|
48
algebra/Q.h
48
algebra/Q.h
@ -13,47 +13,8 @@ class Q
|
||||
using linear_combination_const_iter = ::linear_combination_const_iter<Q>;
|
||||
|
||||
private:
|
||||
// enum steal { STEAL };
|
||||
// enum copy { COPY };
|
||||
// class Q_impl : public refcounted
|
||||
// {
|
||||
// public:
|
||||
// mpq_t x;
|
||||
|
||||
// public:
|
||||
// Q_impl () { mpq_init (x); }
|
||||
// Q_impl (int init)
|
||||
// {
|
||||
// mpq_init (x);
|
||||
// mpq_set_si (x, init, 1);
|
||||
// }
|
||||
|
||||
// Q_impl (copy, mpq_srcptr init)
|
||||
// {
|
||||
// mpq_init (x);
|
||||
// mpq_set (x, init);
|
||||
// }
|
||||
|
||||
// Q_impl (steal, mpq_srcptr init) { x[0] = *init; }
|
||||
// Q_impl (reader &r)
|
||||
// {
|
||||
// mpq_init (x);
|
||||
// r.read_mpz (mpq_numref (x));
|
||||
// r.read_mpz (mpq_denref (x));
|
||||
// }
|
||||
|
||||
// ~Q_impl () { mpq_clear (x); }
|
||||
|
||||
// void write_self (writer &w) const
|
||||
// {
|
||||
// w.write_mpz (mpq_numref (x));
|
||||
// w.write_mpz (mpq_denref (x));
|
||||
// }
|
||||
// };
|
||||
|
||||
// ptr<Q_impl> impl;
|
||||
std::shared_ptr<mpq_class> impl;
|
||||
void write_state() const {
|
||||
void write_state() const {
|
||||
std::cout << "I store the following value " << *this << "\n";
|
||||
std::cout << "Number of objects pointing to the same value " << impl.use_count() << "\n";
|
||||
/* std::cout << "I point to " << impl.get() << "\n"; */
|
||||
@ -246,6 +207,11 @@ class Q
|
||||
int get_count() const {
|
||||
return impl.use_count();
|
||||
}
|
||||
Z get_num() const {
|
||||
return Z(impl.get()->get_num());
|
||||
}
|
||||
Z get_den() const {
|
||||
return Z(impl.get()->get_den());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _KNOTKIT_ALGEBRA_Q_H
|
||||
|
23
algebra/Z.h
23
algebra/Z.h
@ -145,6 +145,24 @@ class Z
|
||||
}
|
||||
}
|
||||
|
||||
Z operator % (const Z& z) const {
|
||||
if(Z(0) < z) {
|
||||
// return Z(*impl.get() % *z.impl.get());
|
||||
mpz_class r;
|
||||
mpz_fdiv_r(r.get_mpz_t(), impl.get()->get_mpz_t(), z.impl.get()->get_mpz_t());
|
||||
return Z(r);
|
||||
}
|
||||
else
|
||||
return *this;
|
||||
}
|
||||
|
||||
Z operator % (unsigned p) const {
|
||||
if(p != 0)
|
||||
return operator % (Z(p));
|
||||
else
|
||||
return *this;
|
||||
}
|
||||
|
||||
Z recip () const {
|
||||
assert(is_unit());
|
||||
return *this;
|
||||
@ -234,6 +252,9 @@ class Z
|
||||
int get_count() const {
|
||||
return impl.use_count();
|
||||
}
|
||||
};
|
||||
|
||||
unsigned get_ui() const {
|
||||
return impl.get()->get_ui();
|
||||
}
|
||||
};
|
||||
#endif // _KNOTKIT_ALGEBRA_Z_H
|
||||
|
@ -1,5 +1,6 @@
|
||||
#ifndef KNOTKIT_ALGEBRA_Z2_H
|
||||
#define KNOTKIT_ALGEBRA_Z2_H
|
||||
#include <algebra/Z.h>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
@ -8,7 +9,6 @@ class Z2
|
||||
{
|
||||
public:
|
||||
using linear_combination = ::linear_combination<Z2>;
|
||||
// typedef linear_combination_iter<Z2> linear_combination_iter;
|
||||
using linear_combination_const_iter = ::linear_combination_const_iter<Z2>;
|
||||
|
||||
private:
|
||||
@ -24,6 +24,7 @@ class Z2
|
||||
x.v = 0;
|
||||
}
|
||||
Z2 (reader &r) { v = r.read_bool (); }
|
||||
Z2 (const Z& z) : v((z % 2).get_ui()) {}
|
||||
~Z2 () { }
|
||||
|
||||
Z2& operator = (const Z2& x) { v = x.v; return *this; }
|
||||
@ -88,5 +89,4 @@ class Z2
|
||||
void show_self () const { std::cout << *this; }
|
||||
void display_self () const { std::cout << *this << "\n"; }
|
||||
};
|
||||
|
||||
#endif //KNOTKIT_ALGEBRA_Z2_H
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef KNOTKIT_ALGEBRA_ZP_H
|
||||
#define KNOTKIT_ALGEBRA_ZP_H
|
||||
|
||||
#include <algebra/Z.h>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
@ -32,6 +32,7 @@ class Zp
|
||||
Zp (Zp&& x) : v(std::move(x.v)) {
|
||||
x.v = 0;
|
||||
}
|
||||
Zp (const Z& z) : v((z % p).get_ui()) {}
|
||||
~Zp () { }
|
||||
|
||||
Zp& operator = (const Zp& x) { v = x.v; return *this; }
|
||||
@ -123,5 +124,4 @@ class Zp
|
||||
void show_self () const { std::cout << v << "(" << p << ")"; }
|
||||
void display_self () const { std::cout << *this << "\n"; }
|
||||
};
|
||||
|
||||
#endif //KNOTKIT_ALGEBRA_ZP_H
|
||||
|
@ -1,3 +1,5 @@
|
||||
#ifndef _KNOTKIT_ALGEBRA_H
|
||||
#define _KNOTKIT_ALGEBRA_H
|
||||
#include <lib/lib.h>
|
||||
|
||||
#ifdef DEBUG_ALGEBRA
|
||||
@ -73,3 +75,5 @@ enum variable { VARIABLE };
|
||||
|
||||
#include <algebra/module.h>
|
||||
#include <algebra/linear_combination.h>
|
||||
|
||||
#endif // _KNOTKIT_ALGEBRA_H
|
||||
|
@ -1,3 +1,5 @@
|
||||
#ifndef _KNOTKIT_ALGEBRA_FRACTION_FIELD_H
|
||||
#define _KNOTKIT_ALGEBRA_FRACTION_FIELD_H
|
||||
|
||||
template<class T> class fraction_field
|
||||
{
|
||||
@ -243,3 +245,5 @@ fraction_field<T>::show_self () const
|
||||
printf (")");
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _KNOTKIT_ALGEBRA_FRACTION_FIELD_H
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
#ifndef _KNOTKIT_ALGEBRA_GRADINGS_H
|
||||
#define _KNOTKIT_ALGEBRA_GRADINGS_H
|
||||
class grading
|
||||
{
|
||||
public:
|
||||
@ -8,6 +9,9 @@ class grading
|
||||
grading () : h(0), q(0) { }
|
||||
grading (int h_, int q_) : h(h_), q(q_) { }
|
||||
grading (const grading &gr) : h(gr.h), q(gr.q) { }
|
||||
grading (grading&& gr) : h(std::move(gr.h)), q(std::move(gr.q)) {
|
||||
gr.h = gr.q = 0;
|
||||
}
|
||||
grading (reader &r)
|
||||
{
|
||||
h = r.read_int ();
|
||||
@ -17,6 +21,12 @@ class grading
|
||||
~grading () { }
|
||||
|
||||
grading &operator = (const grading &gr) { h = gr.h; q = gr.q; return *this; }
|
||||
grading& operator = (grading&& gr) {
|
||||
h = std::move(gr.h);
|
||||
q = std::move(gr.q);
|
||||
gr.h = gr.q = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
grading operator + (const grading &gr) const
|
||||
{
|
||||
@ -61,3 +71,5 @@ class grading
|
||||
void show_self () const;
|
||||
void display_self () const;
|
||||
};
|
||||
|
||||
#endif // _KNOTKIT_ALGEBRA_GRADINGS_H
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
#ifndef _KNOTKIT_ALGEBRA_LINEAR_COMBINATIONS_H
|
||||
#define _KNOTKIT_ALGEBRA_LINEAR_COMBINATIONS_H
|
||||
template<class R> class linear_combination_const_iter;
|
||||
|
||||
template<class R>
|
||||
@ -512,3 +513,5 @@ class linear_combination_const_iter<Z2>
|
||||
unsigned key () const { return i.val (); }
|
||||
Z2 val () { return Z2 (1); }
|
||||
};
|
||||
|
||||
#endif // _KNOTKIT_ALGEBRA_LINEAR_COMBINATIONS_H
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
#ifndef _KNOTKIT_ALGEBRA_MODULE_H
|
||||
#define _KNOTKIT_ALGEBRA_MODULE_H
|
||||
template<class R> class mod_map;
|
||||
|
||||
template<class R> class mod_span;
|
||||
@ -85,8 +86,10 @@ class module : public refcounted
|
||||
ptr<const quotient_module<R> > quotient (ptr<const free_submodule<R> > m) const;
|
||||
|
||||
ptr<const free_submodule<R> > submodule (const mod_span<R> &span) const;
|
||||
|
||||
|
||||
multivariate_laurentpoly<Z> free_poincare_polynomial () const;
|
||||
template<unsigned p>
|
||||
multivariate_laurentpoly<Zp<p>> free_poincare_polynomial () const;
|
||||
multivariate_laurentpoly<Z> free_delta_poincare_polynomial () const;
|
||||
multivariate_laurentpoly<Z> free_ell_poincare_polynomial () const;
|
||||
|
||||
@ -1476,6 +1479,20 @@ module<R>::free_poincare_polynomial () const
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class R> template <unsigned p> multivariate_laurentpoly<Zp<p>>
|
||||
module<R>::free_poincare_polynomial() const {
|
||||
multivariate_laurentpoly<Zp<p>> r;
|
||||
for (unsigned i = 1; i <= free_rank (); i ++)
|
||||
{
|
||||
grading hq = generator_grading (i);
|
||||
multivariate_laurent_monomial m;
|
||||
m.push_exponent (1, hq.h);
|
||||
m.push_exponent (2, hq.q);
|
||||
r.muladdeq (1, m);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class R> multivariate_laurentpoly<Z>
|
||||
module<R>::free_delta_poincare_polynomial () const
|
||||
{
|
||||
@ -2130,3 +2147,5 @@ reader::read_mod ()
|
||||
return module<R>::reader_id_module(id);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _KNOTKIT_ALGEBRA_MODULE_H
|
||||
|
@ -1,4 +1,7 @@
|
||||
|
||||
#ifndef _KNOTKIT_ALGEBRA_MULTIVARIATE_LAURENPOLY_H
|
||||
#define _KNOTKIT_ALGEBRA_MULTIVARIATE_LAURENPOLY_H
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
/* multivariate polynomial in a (vector) variable x with coefficients
|
||||
in T. */
|
||||
|
||||
@ -133,17 +136,31 @@ class multivariate_laurent_monomial
|
||||
if (e != 0)
|
||||
m.push (j, e);
|
||||
}
|
||||
|
||||
|
||||
std::string to_string() const {
|
||||
std::ostringstream res;
|
||||
for (map<unsigned, int>::const_iter i = m; i; i ++) {
|
||||
assert (i.val () != 0);
|
||||
if (i.val () == 1) {
|
||||
res << "x" << std::to_string(i.key());
|
||||
}
|
||||
else {
|
||||
res << "x"
|
||||
<< std::to_string(i.key())
|
||||
<< "^"
|
||||
<< std::to_string(i.val());
|
||||
}
|
||||
}
|
||||
return res.str();
|
||||
}
|
||||
|
||||
friend std::ostream& operator << (std::ostream& os, const multivariate_laurent_monomial& m) {
|
||||
return os << m.to_string();
|
||||
}
|
||||
|
||||
void show_self () const
|
||||
{
|
||||
for (map<unsigned, int>::const_iter i = m; i; i ++)
|
||||
{
|
||||
assert (i.val () != 0);
|
||||
if (i.val () == 1)
|
||||
printf ("x%d", i.key ());
|
||||
else
|
||||
printf ("x%d^%d", i.key (), i.val ());
|
||||
}
|
||||
std::cout << *this;
|
||||
}
|
||||
|
||||
void write_self (writer &w) const { write (w, m); }
|
||||
@ -161,12 +178,11 @@ template<class T>
|
||||
class multivariate_laurentpoly
|
||||
{
|
||||
public:
|
||||
typedef ::linear_combination<multivariate_laurentpoly<T> > linear_combination;
|
||||
typedef ::linear_combination_const_iter<multivariate_laurentpoly<T> >
|
||||
linear_combination_const_iter;
|
||||
using linear_combination = ::linear_combination<multivariate_laurentpoly<T>>;
|
||||
using linear_combination_const_iter = ::linear_combination_const_iter<multivariate_laurentpoly<T> >;
|
||||
|
||||
public:
|
||||
typedef multivariate_laurent_monomial monomial;
|
||||
using monomial = multivariate_laurent_monomial;
|
||||
|
||||
map<monomial, T> coeffs;
|
||||
|
||||
@ -294,6 +310,7 @@ class multivariate_laurentpoly
|
||||
|
||||
unsigned card () const { return coeffs.card (); }
|
||||
pair<monomial, T> head () const { return coeffs.head (); }
|
||||
pair<monomial, T> tail() const { return coeffs.tail(); }
|
||||
|
||||
multivariate_laurentpoly &operator += (const multivariate_laurentpoly &p);
|
||||
multivariate_laurentpoly &operator -= (const multivariate_laurentpoly &p);
|
||||
@ -351,9 +368,14 @@ class multivariate_laurentpoly
|
||||
T::show_ring ();
|
||||
printf ("[x_1^+/-1, ..., x_n^+/-1]");
|
||||
}
|
||||
|
||||
void display_self () const { show_self (); newline (); }
|
||||
void show_self () const;
|
||||
|
||||
std::string to_string() const;
|
||||
void display_self () const {
|
||||
std::cout << *this << "\n";
|
||||
}
|
||||
void show_self () const {
|
||||
std::cout << *this;
|
||||
}
|
||||
void write_self (writer &w) const { write (w, coeffs); }
|
||||
};
|
||||
|
||||
@ -444,42 +466,41 @@ multivariate_laurentpoly<T>::check () const
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T> void
|
||||
multivariate_laurentpoly<T>::show_self () const
|
||||
{
|
||||
template<class T>
|
||||
std::string multivariate_laurentpoly<T>::to_string() const {
|
||||
std::ostringstream res;
|
||||
unsigned first = 1;
|
||||
for (typename map<monomial, T>::const_iter i = coeffs; i; i ++)
|
||||
{
|
||||
monomial m = i.key ();
|
||||
T c = i.val ();
|
||||
for (typename map<monomial, T>::const_iter i = coeffs; i; i ++) {
|
||||
monomial m = i.key ();
|
||||
T c = i.val ();
|
||||
assert (c != 0);
|
||||
|
||||
if (first)
|
||||
first = 0;
|
||||
else
|
||||
res << " + ";
|
||||
|
||||
assert (c != 0);
|
||||
|
||||
if (first)
|
||||
first = 0;
|
||||
if (m == 1) {
|
||||
if (c == 1)
|
||||
res << "1";
|
||||
else
|
||||
printf (" + ");
|
||||
|
||||
if (m == 1)
|
||||
{
|
||||
if (c == 1)
|
||||
printf ("1");
|
||||
else
|
||||
show (c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c != 1)
|
||||
{
|
||||
show (c);
|
||||
printf ("*");
|
||||
}
|
||||
|
||||
show (m);
|
||||
}
|
||||
res << c;
|
||||
}
|
||||
else {
|
||||
if (c != 1) {
|
||||
res << c << "*";
|
||||
}
|
||||
res << m;
|
||||
}
|
||||
}
|
||||
if (first)
|
||||
printf ("0");
|
||||
res << "0";
|
||||
return res.str();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::ostream& operator << (std::ostream& os, const multivariate_laurentpoly<T>& pol) {
|
||||
return os << pol.to_string();
|
||||
}
|
||||
|
||||
// functions below were added to verify several periodicity criteria
|
||||
@ -506,30 +527,4 @@ multivariate_laurentpoly<T> invert_variable(const multivariate_laurentpoly<T>& p
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool check_przytycki_cong(const multivariate_laurentpoly<T>& pol, const int prime,
|
||||
const int exponent = 1, const unsigned index = 1) {
|
||||
multivariate_laurentpoly<T> result;
|
||||
for(typename map<multivariate_laurent_monomial, T>::const_iter i = pol.coeffs; i; i++) {
|
||||
multivariate_laurent_monomial mon = i.key();
|
||||
T c = i.val();
|
||||
multivariate_laurent_monomial mon2;
|
||||
for(typename map<unsigned, int>::const_iter i = mon.m; i; i++) {
|
||||
// still need to handle the coefficient
|
||||
// i.e. we need to take c % p
|
||||
if(i.key() == index) {
|
||||
int v = i.val() % (2 * prime);
|
||||
if(v < 0) v += (2 * prime);
|
||||
mon2 *= multivariate_laurent_monomial(VARIABLE, i.key(), v);
|
||||
c.display_self();
|
||||
printf("Old: key = %d, val = %d\n", i.key(), i.val());
|
||||
printf("New: key = %d, val = %d\n", i.key(), v);
|
||||
}
|
||||
else
|
||||
mon2 *= multivariate_laurent_monomial(VARIABLE, i.key(), i.val());
|
||||
}
|
||||
result += multivariate_laurentpoly<T>(c, mon2);
|
||||
}
|
||||
result.display_self();
|
||||
return true;
|
||||
}
|
||||
#endif // _KNOTKIT_ALGEBRA_MULTIVARIATE_LAURENPOLY_H
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
#ifndef _KNOTKIT_ALGEBRA_MULTIVARIATE_POLYNOMIAL_H
|
||||
#define _KNOTKIT_ALGEBRA_MULTIVARIATE_POLYNOMIAL_H
|
||||
/* multivariate polynomial in a (vector) variable x with coefficients
|
||||
in T. */
|
||||
|
||||
@ -499,3 +500,5 @@ multivariate_polynomial<T, n>::show_self () const
|
||||
if (first)
|
||||
printf ("0");
|
||||
}
|
||||
|
||||
#endif // _KNOTKIT_ALGEBRA_MULTIVARIATE_POLYNOMIAL_H
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
#ifndef _KNOTKIT_ALGEBRA_POLYNOMIAL_H
|
||||
#define _KNOTKIT_ALGEBRA_POLYNOMIAL_H
|
||||
/* univariate polynomial in a single variable `x' with coefficients in
|
||||
T. */
|
||||
|
||||
@ -512,3 +513,5 @@ class polynomial<Z2>
|
||||
void display_self () const { show_self (); newline (); }
|
||||
void show_self () const;
|
||||
};
|
||||
|
||||
#endif // _KNOTKIT_ALGEBRA_POLYNOMIAL_H
|
||||
|
193
kk.cpp
193
kk.cpp
@ -1,4 +1,7 @@
|
||||
|
||||
#include <knotkit.h>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
const char *program_name;
|
||||
|
||||
@ -72,7 +75,6 @@ const char *invariant = 0;
|
||||
const char *field = "Z2";
|
||||
|
||||
knot_diagram kd;
|
||||
|
||||
bool reduced = 0;
|
||||
|
||||
class hg_grading_mapper
|
||||
@ -250,43 +252,131 @@ compute_gss ()
|
||||
tex_footer ();
|
||||
}
|
||||
|
||||
multivariate_laurentpoly<Z> compute_jones(const knot_diagram& k, bool reduced) {
|
||||
multivariate_laurentpoly<Z> compute_jones(const knot_diagram& k, bool reduced = false) {
|
||||
using polynomial = multivariate_laurentpoly<Z>;
|
||||
cube<Z2> c(kd, reduced);
|
||||
ptr<const module<Z2> > C = c.khC;
|
||||
mod_map<Z2> d = c.compute_d(1, 0, 0, 0, 0);
|
||||
chain_complex_simplifier<Z2> s(C, d, maybe<int>(1), maybe<int>(0));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
multivariate_laurentpoly<Z> jones;
|
||||
polynomial jones;
|
||||
for(uint i = 1; i <= c.n_generators; ++i) {
|
||||
grading gr = c.compute_generator_grading(i);
|
||||
if(gr.h % 2 == 0) {
|
||||
jones += multivariate_laurentpoly<Z>(1, VARIABLE, 1, gr.q);
|
||||
jones += polynomial(1, VARIABLE, 1, gr.q);
|
||||
}
|
||||
else {
|
||||
jones += multivariate_laurentpoly<Z>(-1, VARIABLE, 1, gr.q);
|
||||
jones += polynomial(-1, VARIABLE, 1, gr.q);
|
||||
}
|
||||
}
|
||||
return jones;
|
||||
}
|
||||
|
||||
template<class R>
|
||||
multivariate_laurentpoly<Z> compute_khp(const knot_diagram& k, bool reduced) {
|
||||
cube<R> c(kd,reduced);
|
||||
multivariate_laurentpoly<Z> compute_khp(const knot_diagram& k, bool reduced = false) {
|
||||
cube<R> c (kd, reduced);
|
||||
ptr<const module<R> > C = c.khC;
|
||||
mod_map<R> d = c.compute_d(1, 0, 0, 0, 0);
|
||||
chain_complex_simplifier<R> s(C, d, maybe<int>(1), maybe<int>(0));
|
||||
mod_map<R> d = c.compute_d (1, 0, 0, 0, 0);
|
||||
|
||||
unsigned m = kd.num_components ();
|
||||
hg_grading_mapper mapper (m);
|
||||
|
||||
chain_complex_simplifier<R> s (C, d,
|
||||
maybe<int> (1), maybe<int> (0));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
multivariate_laurentpoly<Z> khp;
|
||||
for(uint i = 1; i <= C->dim(); ++i) {
|
||||
grading gr = C->generator_grading(i);
|
||||
multivariate_laurentpoly<Z> p1 = multivariate_laurentpoly<Z>(1, VARIABLE, 0, gr.h);
|
||||
multivariate_laurentpoly<Z> p2 = multivariate_laurentpoly<Z>(1, VARIABLE, 1, gr.q);
|
||||
multivariate_laurentpoly<Z> p3 = p1 * p2;
|
||||
khp += p3;
|
||||
return C->free_poincare_polynomial();
|
||||
}
|
||||
|
||||
template<class R>
|
||||
int compute_s_inv(knot_diagram& kd) {
|
||||
unsigned m = kd.num_components ();
|
||||
if (m != 1) {
|
||||
fprintf (stderr, "error: s-invariant only defined for knots\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
return khp;
|
||||
|
||||
cube<R> c (kd, 0);
|
||||
ptr<const module<R> > C = c.khC;
|
||||
|
||||
mod_map<R> 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);
|
||||
|
||||
int k = 0;
|
||||
for (;;) {
|
||||
chain_complex_simplifier<R> s (C, d,
|
||||
maybe<int> (1),
|
||||
maybe<int> (2*k));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
k ++;
|
||||
|
||||
if (d == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
assert (C->dim () == 2);
|
||||
grading gr1 = C->generator_grading (1),
|
||||
gr2 = C->generator_grading (2);
|
||||
C->free_poincare_polynomial().display_self();
|
||||
int qmin = gr1.q,
|
||||
qmax = gr2.q;
|
||||
if (qmax < qmin)
|
||||
std::swap (qmin, qmax);
|
||||
|
||||
assert (qmax == qmin + 2);
|
||||
return qmin + 1;
|
||||
}
|
||||
|
||||
template<class R>
|
||||
void check_periodicity_criterion(knot_diagram kd, int prime = 5){
|
||||
using monomial = multivariate_laurent_monomial;
|
||||
using polynomial = multivariate_laurentpoly<Z>;
|
||||
unsigned m = kd.num_components();
|
||||
Test_type t = Test_type::all;
|
||||
if(m != 1) {
|
||||
std::cerr << "Error: for now this only works for knots\n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
polynomial khp, lee_p;
|
||||
// Adding braces so that the cube can be destroyed
|
||||
// when its not needed anymore
|
||||
{
|
||||
cube<R> c(kd,0);
|
||||
ptr<const module<R>> C = c.khC;
|
||||
mod_map<R> 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 polynomial..." << "\n";
|
||||
chain_complex_simplifier<R> s(C, d, maybe<int>(1), maybe<int>(0));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
khp = C->free_poincare_polynomial();
|
||||
|
||||
// computing Lee homology
|
||||
if(verbose)
|
||||
std::cout << "Computing Lee polynomial..." << "\n";
|
||||
chain_complex_simplifier<R> s1(C, d, maybe<int>(1), maybe<int>(2));
|
||||
C = s1.new_C;
|
||||
d = s1.new_d;
|
||||
assert(C->dim() == 2);
|
||||
lee_p = C->free_poincare_polynomial();
|
||||
}
|
||||
if(verbose) {
|
||||
std::cout << "Khovanov polynomial = "
|
||||
<< khp << "\n"
|
||||
<< "Lee polynomial = "
|
||||
<< lee_p << "\n";
|
||||
}
|
||||
periodicity_checker pc = periodicity_checker(khp, lee_p, prime, t);
|
||||
pc();
|
||||
}
|
||||
|
||||
template<class R> void
|
||||
@ -413,48 +503,10 @@ compute_invariant ()
|
||||
tex_footer ();
|
||||
}
|
||||
else if (!strcmp (invariant, "s"))
|
||||
{
|
||||
unsigned m = kd.num_components ();
|
||||
if (m != 1)
|
||||
{
|
||||
fprintf (stderr, "error: s-invariant only defined for knots\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
cube<R> c (kd, 0);
|
||||
ptr<const module<R> > C = c.khC;
|
||||
|
||||
mod_map<R> 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);
|
||||
|
||||
int k = 0;
|
||||
for (;;)
|
||||
{
|
||||
chain_complex_simplifier<R> s (C, d,
|
||||
maybe<int> (1), maybe<int> (2*k));
|
||||
C = s.new_C;
|
||||
d = s.new_d;
|
||||
k ++;
|
||||
|
||||
if (d == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
assert (C->dim () == 2);
|
||||
grading gr1 = C->generator_grading (1),
|
||||
gr2 = C->generator_grading (2);
|
||||
|
||||
int qmin = gr1.q,
|
||||
qmax = gr2.q;
|
||||
if (qmax < qmin)
|
||||
std::swap (qmin, qmax);
|
||||
|
||||
assert (qmax == qmin + 2);
|
||||
|
||||
fprintf (outfp, "s(%s; %s) = %d\n", knot, field, qmin + 1);
|
||||
}
|
||||
{
|
||||
int s = compute_s_inv<R>(kd);
|
||||
fprintf (outfp, "s(%s; %s) = %d\n", knot, field, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: unknown invariant %s\n", invariant);
|
||||
@ -753,14 +805,14 @@ main (int argc, char **argv)
|
||||
inv_jones_pol.display_self();
|
||||
multivariate_laurentpoly<Z> diff = jones_pol - inv_jones_pol;
|
||||
diff.display_self();
|
||||
check_przytycki_cong(diff, 3);
|
||||
check_przytycki_cong<Z,Zp<5>>(diff, 5);
|
||||
}
|
||||
else if(!strcmp(invariant, "khp")) {
|
||||
multivariate_laurentpoly<Z> khp;
|
||||
if(!strcmp(field, "Z2"))
|
||||
khp = compute_khp<Z2>(kd, reduced);
|
||||
else if(!strcmp(field, "Z3"))
|
||||
khp = compute_khp<Zp<3> >(kd, reduced);
|
||||
khp = compute_khp<Zp<3>>(kd, reduced);
|
||||
else if(!strcmp(field, "Q"))
|
||||
khp = compute_khp<Q>(kd, reduced);
|
||||
else
|
||||
@ -771,6 +823,25 @@ main (int argc, char **argv)
|
||||
printf("Khovanov polynomial of %s is equal to (coefficients %s):\n", knot, field);
|
||||
khp.display_self();
|
||||
}
|
||||
else if(!strcmp(invariant, "periodicity_congruence")) {
|
||||
if(!strcmp(field, "Z2")) {
|
||||
// first we check whether period is a prime
|
||||
if(period == 2 || period == 3) {
|
||||
std::cerr << "The criterion does not work for period = " << period << "\n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
auto result = find(primes.begin(), primes.end(), period);
|
||||
if(result == primes.end()) {
|
||||
std::cerr << "For now it is possible to check periodicity for primes up to 31" << "\n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
check_periodicity_criterion<Z2>(kd,period);
|
||||
}
|
||||
else {
|
||||
std::cerr << "error: for now this function is only defined for Z2 coefficients..." << "\n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strcmp (field, "Z2"))
|
||||
|
169
periodicity.cpp
Normal file
169
periodicity.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
#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.";
|
||||
}
|
||||
}
|
||||
}
|
135
periodicity.h
Normal file
135
periodicity.h
Normal file
@ -0,0 +1,135 @@
|
||||
#ifndef _KNOTKIT_PERIODICITY_H
|
||||
#define _KNOTKIT_PERIODICITY_H
|
||||
|
||||
#include <algebra/algebra.h>
|
||||
#include <vector>
|
||||
|
||||
extern bool verbose;
|
||||
extern const char* knot;
|
||||
|
||||
int period = 5;
|
||||
std::vector<int> primes = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
|
||||
|
||||
template<class T>
|
||||
class congruence_checker {
|
||||
using polynomial = multivariate_laurentpoly<T>;
|
||||
using monomial = multivariate_laurent_monomial;
|
||||
|
||||
int prime;
|
||||
unsigned index;
|
||||
unsigend ev_index;
|
||||
|
||||
polynomial prepare_polynomial(const polynomial& pol) const {
|
||||
return (pol - invert_variable(pol, index)).evaluate(-1, ev_index);
|
||||
}
|
||||
|
||||
bool reduce (const polynomial& pol) const;
|
||||
|
||||
public:
|
||||
congruence_checker(int pprime = 5,
|
||||
unsigned ind = 2,
|
||||
unsigned ev_ind = 1) :
|
||||
prime(pprime), index(ind), ev_index(ev_ind) {}
|
||||
|
||||
congruence_checker(const congruence_checker& cc) =default;
|
||||
congruence_checker(congruence_checker&& cc) =default;
|
||||
|
||||
~congruence_checker() {};
|
||||
|
||||
congruence_checker& operator= (const congruence_checker&& cc) =default;
|
||||
congruence_checker& operator= (congruence_checker&& cc) =default;
|
||||
|
||||
bool operator () (const polynomial& pol) const {
|
||||
return reduce(prepare_polynomial(pol));
|
||||
}
|
||||
};
|
||||
|
||||
enum class Test_type {
|
||||
przytycki_criterion,
|
||||
BKP_criterion,
|
||||
all
|
||||
};
|
||||
|
||||
class periodicity_checker {
|
||||
using polynomial = multivariate_laurentpoly;
|
||||
using monomial = multivariate_laurent_monomial;
|
||||
|
||||
const unsigned ev_index = 1;
|
||||
const unsigned index = 2;
|
||||
|
||||
int prime;
|
||||
|
||||
polynomial<Z> khp;
|
||||
polynomial<Z> leep;
|
||||
|
||||
polynomial<Z> quotient;
|
||||
polynomial<Z> remainder;
|
||||
|
||||
polynomial<Z> mul;
|
||||
|
||||
Test_type type;
|
||||
|
||||
void write_test_result(bool result) const {
|
||||
std::cout << knot;
|
||||
if(result)
|
||||
std::cout << " may be ";
|
||||
else
|
||||
std::cout << " is not ";
|
||||
std::cout << prime << "-periodic.\n";
|
||||
|
||||
}
|
||||
|
||||
polynomial<Z> divide(const polynomial<Z>& kh, const polynomial<Z>& lee) const;
|
||||
|
||||
std::pair<polynomial<Z>, polynomial<Z>>
|
||||
divide_p(const polynomial<Z>& q) const;
|
||||
|
||||
public:
|
||||
periodicity_checker(polynomial<Z> kh,
|
||||
polynomial<Z> lee,
|
||||
int p = 5,
|
||||
Test_type t = Test_type::all) :
|
||||
khp(kh),
|
||||
leep(lee),
|
||||
prime(p),
|
||||
type(t) {
|
||||
// check if prime is in primes
|
||||
|
||||
// compute mul
|
||||
mul = polynomial(Z(1)) + polynomial(1, VARIABLE, ev_index) * polynomial(1, VARIABLE, index, 2);
|
||||
|
||||
// compute quotient and remainder
|
||||
std::pair<polynomial<Z>, polynomial<Z>>
|
||||
p = divide_p(divide(khp, leep));
|
||||
quotient = std::get<0>(p);
|
||||
remainder = std::get<1>(p);
|
||||
}
|
||||
|
||||
periodicity_checker(const periodicity_checker& pc) =default;
|
||||
periodicity_checker(periodicity_checker&& pc) =default;
|
||||
|
||||
periodicity_checker& operator= (const periodicity_checker& pc) =default;
|
||||
periodicity_checker& operator= (periodicity_checker&& pc) =default;
|
||||
|
||||
void operator () () const {
|
||||
if(type == Test_type::przytycki_criterion ||
|
||||
type == Test_type::all) {
|
||||
std::cout << "Przytycki's test: ";
|
||||
write_test_result(przytycki_test());
|
||||
}
|
||||
if(type == Test_type::BKP_criterion ||
|
||||
type == Test_type::all) {
|
||||
std::cout << "BKP test: ";
|
||||
write_test_result(BKP_test);
|
||||
}
|
||||
}
|
||||
|
||||
bool przytycki_test() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BKP_test() const {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif // _KNOTKIT_PERIODICITY_H
|
Loading…
Reference in New Issue
Block a user