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]*
|
/parallel.cmd.[eo]*
|
||||||
/save
|
/save
|
||||||
*/save
|
*/save
|
||||||
|
/org
|
||||||
|
4
Makefile
4
Makefile
@ -11,7 +11,7 @@ CXX = g++ -std=c++11
|
|||||||
INCLUDES = -I. -I/opt/local/include
|
INCLUDES = -I. -I/opt/local/include
|
||||||
|
|
||||||
# OPTFLAGS = -g
|
# OPTFLAGS = -g
|
||||||
OPTFLAGS = -O2 -g
|
OPTFLAGS = -O2 -g -pg
|
||||||
# OPTFLAGS = -O2 -g -DNDEBUG
|
# OPTFLAGS = -O2 -g -DNDEBUG
|
||||||
|
|
||||||
LDFLAGS = -L/opt/local/lib
|
LDFLAGS = -L/opt/local/lib
|
||||||
@ -55,7 +55,7 @@ all: kk
|
|||||||
$(CXX) -c $(CXXFLAGS) $< -o $@
|
$(CXX) -c $(CXXFLAGS) $< -o $@
|
||||||
|
|
||||||
kk: kk.o $(COMMON_OBJS)
|
kk: kk.o $(COMMON_OBJS)
|
||||||
$(CXX) $(LDFLAGS) -o kk $^ $(LIBS)
|
$(CXX) $(LDFLAGS) -pg -o kk $^ $(LIBS)
|
||||||
|
|
||||||
main: main.o $(COMMON_OBJS)
|
main: main.o $(COMMON_OBJS)
|
||||||
$(CXX) $(LDFLAGS) -o main $^ $(LIBS)
|
$(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>;
|
using linear_combination_const_iter = ::linear_combination_const_iter<Q>;
|
||||||
|
|
||||||
private:
|
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;
|
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 << "I store the following value " << *this << "\n";
|
||||||
std::cout << "Number of objects pointing to the same value " << impl.use_count() << "\n";
|
std::cout << "Number of objects pointing to the same value " << impl.use_count() << "\n";
|
||||||
/* std::cout << "I point to " << impl.get() << "\n"; */
|
/* std::cout << "I point to " << impl.get() << "\n"; */
|
||||||
@ -246,6 +207,11 @@ class Q
|
|||||||
int get_count() const {
|
int get_count() const {
|
||||||
return impl.use_count();
|
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
|
#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 {
|
Z recip () const {
|
||||||
assert(is_unit());
|
assert(is_unit());
|
||||||
return *this;
|
return *this;
|
||||||
@ -234,6 +252,9 @@ class Z
|
|||||||
int get_count() const {
|
int get_count() const {
|
||||||
return impl.use_count();
|
return impl.use_count();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
unsigned get_ui() const {
|
||||||
|
return impl.get()->get_ui();
|
||||||
|
}
|
||||||
|
};
|
||||||
#endif // _KNOTKIT_ALGEBRA_Z_H
|
#endif // _KNOTKIT_ALGEBRA_Z_H
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#ifndef KNOTKIT_ALGEBRA_Z2_H
|
#ifndef KNOTKIT_ALGEBRA_Z2_H
|
||||||
#define KNOTKIT_ALGEBRA_Z2_H
|
#define KNOTKIT_ALGEBRA_Z2_H
|
||||||
|
#include <algebra/Z.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -8,7 +9,6 @@ class Z2
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using linear_combination = ::linear_combination<Z2>;
|
using linear_combination = ::linear_combination<Z2>;
|
||||||
// typedef linear_combination_iter<Z2> linear_combination_iter;
|
|
||||||
using linear_combination_const_iter = ::linear_combination_const_iter<Z2>;
|
using linear_combination_const_iter = ::linear_combination_const_iter<Z2>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -24,6 +24,7 @@ class Z2
|
|||||||
x.v = 0;
|
x.v = 0;
|
||||||
}
|
}
|
||||||
Z2 (reader &r) { v = r.read_bool (); }
|
Z2 (reader &r) { v = r.read_bool (); }
|
||||||
|
Z2 (const Z& z) : v((z % 2).get_ui()) {}
|
||||||
~Z2 () { }
|
~Z2 () { }
|
||||||
|
|
||||||
Z2& operator = (const Z2& x) { v = x.v; return *this; }
|
Z2& operator = (const Z2& x) { v = x.v; return *this; }
|
||||||
@ -88,5 +89,4 @@ class Z2
|
|||||||
void show_self () const { std::cout << *this; }
|
void show_self () const { std::cout << *this; }
|
||||||
void display_self () const { std::cout << *this << "\n"; }
|
void display_self () const { std::cout << *this << "\n"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //KNOTKIT_ALGEBRA_Z2_H
|
#endif //KNOTKIT_ALGEBRA_Z2_H
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#ifndef KNOTKIT_ALGEBRA_ZP_H
|
#ifndef KNOTKIT_ALGEBRA_ZP_H
|
||||||
#define KNOTKIT_ALGEBRA_ZP_H
|
#define KNOTKIT_ALGEBRA_ZP_H
|
||||||
|
#include <algebra/Z.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -32,6 +32,7 @@ class Zp
|
|||||||
Zp (Zp&& x) : v(std::move(x.v)) {
|
Zp (Zp&& x) : v(std::move(x.v)) {
|
||||||
x.v = 0;
|
x.v = 0;
|
||||||
}
|
}
|
||||||
|
Zp (const Z& z) : v((z % p).get_ui()) {}
|
||||||
~Zp () { }
|
~Zp () { }
|
||||||
|
|
||||||
Zp& operator = (const Zp& x) { v = x.v; return *this; }
|
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 show_self () const { std::cout << v << "(" << p << ")"; }
|
||||||
void display_self () const { std::cout << *this << "\n"; }
|
void display_self () const { std::cout << *this << "\n"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //KNOTKIT_ALGEBRA_ZP_H
|
#endif //KNOTKIT_ALGEBRA_ZP_H
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#ifndef _KNOTKIT_ALGEBRA_H
|
||||||
|
#define _KNOTKIT_ALGEBRA_H
|
||||||
#include <lib/lib.h>
|
#include <lib/lib.h>
|
||||||
|
|
||||||
#ifdef DEBUG_ALGEBRA
|
#ifdef DEBUG_ALGEBRA
|
||||||
@ -73,3 +75,5 @@ enum variable { VARIABLE };
|
|||||||
|
|
||||||
#include <algebra/module.h>
|
#include <algebra/module.h>
|
||||||
#include <algebra/linear_combination.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
|
template<class T> class fraction_field
|
||||||
{
|
{
|
||||||
@ -243,3 +245,5 @@ fraction_field<T>::show_self () const
|
|||||||
printf (")");
|
printf (")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // _KNOTKIT_ALGEBRA_FRACTION_FIELD_H
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
|
#ifndef _KNOTKIT_ALGEBRA_GRADINGS_H
|
||||||
|
#define _KNOTKIT_ALGEBRA_GRADINGS_H
|
||||||
class grading
|
class grading
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -8,6 +9,9 @@ class grading
|
|||||||
grading () : h(0), q(0) { }
|
grading () : h(0), q(0) { }
|
||||||
grading (int h_, int q_) : h(h_), q(q_) { }
|
grading (int h_, int q_) : h(h_), q(q_) { }
|
||||||
grading (const grading &gr) : h(gr.h), q(gr.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)
|
grading (reader &r)
|
||||||
{
|
{
|
||||||
h = r.read_int ();
|
h = r.read_int ();
|
||||||
@ -17,6 +21,12 @@ class grading
|
|||||||
~grading () { }
|
~grading () { }
|
||||||
|
|
||||||
grading &operator = (const grading &gr) { h = gr.h; q = gr.q; return *this; }
|
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
|
grading operator + (const grading &gr) const
|
||||||
{
|
{
|
||||||
@ -61,3 +71,5 @@ class grading
|
|||||||
void show_self () const;
|
void show_self () const;
|
||||||
void display_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> class linear_combination_const_iter;
|
||||||
|
|
||||||
template<class R>
|
template<class R>
|
||||||
@ -512,3 +513,5 @@ class linear_combination_const_iter<Z2>
|
|||||||
unsigned key () const { return i.val (); }
|
unsigned key () const { return i.val (); }
|
||||||
Z2 val () { return Z2 (1); }
|
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_map;
|
||||||
|
|
||||||
template<class R> class mod_span;
|
template<class R> class mod_span;
|
||||||
@ -87,6 +88,8 @@ class module : public refcounted
|
|||||||
ptr<const free_submodule<R> > submodule (const mod_span<R> &span) const;
|
ptr<const free_submodule<R> > submodule (const mod_span<R> &span) const;
|
||||||
|
|
||||||
multivariate_laurentpoly<Z> free_poincare_polynomial () 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_delta_poincare_polynomial () const;
|
||||||
multivariate_laurentpoly<Z> free_ell_poincare_polynomial () const;
|
multivariate_laurentpoly<Z> free_ell_poincare_polynomial () const;
|
||||||
|
|
||||||
@ -1476,6 +1479,20 @@ module<R>::free_poincare_polynomial () const
|
|||||||
return r;
|
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>
|
template<class R> multivariate_laurentpoly<Z>
|
||||||
module<R>::free_delta_poincare_polynomial () const
|
module<R>::free_delta_poincare_polynomial () const
|
||||||
{
|
{
|
||||||
@ -2130,3 +2147,5 @@ reader::read_mod ()
|
|||||||
return module<R>::reader_id_module(id);
|
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
|
/* multivariate polynomial in a (vector) variable x with coefficients
|
||||||
in T. */
|
in T. */
|
||||||
|
|
||||||
@ -134,16 +137,30 @@ class multivariate_laurent_monomial
|
|||||||
m.push (j, e);
|
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
|
void show_self () const
|
||||||
{
|
{
|
||||||
for (map<unsigned, int>::const_iter i = m; i; i ++)
|
std::cout << *this;
|
||||||
{
|
|
||||||
assert (i.val () != 0);
|
|
||||||
if (i.val () == 1)
|
|
||||||
printf ("x%d", i.key ());
|
|
||||||
else
|
|
||||||
printf ("x%d^%d", i.key (), i.val ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_self (writer &w) const { write (w, m); }
|
void write_self (writer &w) const { write (w, m); }
|
||||||
@ -161,12 +178,11 @@ template<class T>
|
|||||||
class multivariate_laurentpoly
|
class multivariate_laurentpoly
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef ::linear_combination<multivariate_laurentpoly<T> > linear_combination;
|
using linear_combination = ::linear_combination<multivariate_laurentpoly<T>>;
|
||||||
typedef ::linear_combination_const_iter<multivariate_laurentpoly<T> >
|
using linear_combination_const_iter = ::linear_combination_const_iter<multivariate_laurentpoly<T> >;
|
||||||
linear_combination_const_iter;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef multivariate_laurent_monomial monomial;
|
using monomial = multivariate_laurent_monomial;
|
||||||
|
|
||||||
map<monomial, T> coeffs;
|
map<monomial, T> coeffs;
|
||||||
|
|
||||||
@ -294,6 +310,7 @@ class multivariate_laurentpoly
|
|||||||
|
|
||||||
unsigned card () const { return coeffs.card (); }
|
unsigned card () const { return coeffs.card (); }
|
||||||
pair<monomial, T> head () const { return coeffs.head (); }
|
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);
|
||||||
multivariate_laurentpoly &operator -= (const multivariate_laurentpoly &p);
|
multivariate_laurentpoly &operator -= (const multivariate_laurentpoly &p);
|
||||||
@ -352,8 +369,13 @@ class multivariate_laurentpoly
|
|||||||
printf ("[x_1^+/-1, ..., x_n^+/-1]");
|
printf ("[x_1^+/-1, ..., x_n^+/-1]");
|
||||||
}
|
}
|
||||||
|
|
||||||
void display_self () const { show_self (); newline (); }
|
std::string to_string() const;
|
||||||
void show_self () 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); }
|
void write_self (writer &w) const { write (w, coeffs); }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -444,42 +466,41 @@ multivariate_laurentpoly<T>::check () const
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<class T> void
|
template<class T>
|
||||||
multivariate_laurentpoly<T>::show_self () const
|
std::string multivariate_laurentpoly<T>::to_string() const {
|
||||||
{
|
std::ostringstream res;
|
||||||
unsigned first = 1;
|
unsigned first = 1;
|
||||||
for (typename map<monomial, T>::const_iter i = coeffs; i; i ++)
|
for (typename map<monomial, T>::const_iter i = coeffs; i; i ++) {
|
||||||
{
|
monomial m = i.key ();
|
||||||
monomial m = i.key ();
|
T c = i.val ();
|
||||||
T c = i.val ();
|
assert (c != 0);
|
||||||
|
|
||||||
assert (c != 0);
|
if (first)
|
||||||
|
first = 0;
|
||||||
|
else
|
||||||
|
res << " + ";
|
||||||
|
|
||||||
if (first)
|
if (m == 1) {
|
||||||
first = 0;
|
if (c == 1)
|
||||||
|
res << "1";
|
||||||
else
|
else
|
||||||
printf (" + ");
|
res << c;
|
||||||
|
|
||||||
if (m == 1)
|
|
||||||
{
|
|
||||||
if (c == 1)
|
|
||||||
printf ("1");
|
|
||||||
else
|
|
||||||
show (c);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (c != 1)
|
|
||||||
{
|
|
||||||
show (c);
|
|
||||||
printf ("*");
|
|
||||||
}
|
|
||||||
|
|
||||||
show (m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (c != 1) {
|
||||||
|
res << c << "*";
|
||||||
|
}
|
||||||
|
res << m;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (first)
|
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
|
// 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
#endif // _KNOTKIT_ALGEBRA_MULTIVARIATE_LAURENPOLY_H
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
@ -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
|
/* multivariate polynomial in a (vector) variable x with coefficients
|
||||||
in T. */
|
in T. */
|
||||||
|
|
||||||
@ -499,3 +500,5 @@ multivariate_polynomial<T, n>::show_self () const
|
|||||||
if (first)
|
if (first)
|
||||||
printf ("0");
|
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
|
/* univariate polynomial in a single variable `x' with coefficients in
|
||||||
T. */
|
T. */
|
||||||
|
|
||||||
@ -512,3 +513,5 @@ class polynomial<Z2>
|
|||||||
void display_self () const { show_self (); newline (); }
|
void display_self () const { show_self (); newline (); }
|
||||||
void show_self () const;
|
void show_self () const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // _KNOTKIT_ALGEBRA_POLYNOMIAL_H
|
||||||
|
193
kk.cpp
193
kk.cpp
@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
#include <knotkit.h>
|
#include <knotkit.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
const char *program_name;
|
const char *program_name;
|
||||||
|
|
||||||
@ -72,7 +75,6 @@ const char *invariant = 0;
|
|||||||
const char *field = "Z2";
|
const char *field = "Z2";
|
||||||
|
|
||||||
knot_diagram kd;
|
knot_diagram kd;
|
||||||
|
|
||||||
bool reduced = 0;
|
bool reduced = 0;
|
||||||
|
|
||||||
class hg_grading_mapper
|
class hg_grading_mapper
|
||||||
@ -250,43 +252,131 @@ compute_gss ()
|
|||||||
tex_footer ();
|
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);
|
cube<Z2> c(kd, reduced);
|
||||||
ptr<const module<Z2> > C = c.khC;
|
ptr<const module<Z2> > C = c.khC;
|
||||||
mod_map<Z2> d = c.compute_d(1, 0, 0, 0, 0);
|
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));
|
chain_complex_simplifier<Z2> s(C, d, maybe<int>(1), maybe<int>(0));
|
||||||
C = s.new_C;
|
C = s.new_C;
|
||||||
d = s.new_d;
|
d = s.new_d;
|
||||||
multivariate_laurentpoly<Z> jones;
|
polynomial jones;
|
||||||
for(uint i = 1; i <= c.n_generators; ++i) {
|
for(uint i = 1; i <= c.n_generators; ++i) {
|
||||||
grading gr = c.compute_generator_grading(i);
|
grading gr = c.compute_generator_grading(i);
|
||||||
if(gr.h % 2 == 0) {
|
if(gr.h % 2 == 0) {
|
||||||
jones += multivariate_laurentpoly<Z>(1, VARIABLE, 1, gr.q);
|
jones += polynomial(1, VARIABLE, 1, gr.q);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jones += multivariate_laurentpoly<Z>(-1, VARIABLE, 1, gr.q);
|
jones += polynomial(-1, VARIABLE, 1, gr.q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return jones;
|
return jones;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class R>
|
template<class R>
|
||||||
multivariate_laurentpoly<Z> compute_khp(const knot_diagram& k, bool reduced) {
|
multivariate_laurentpoly<Z> compute_khp(const knot_diagram& k, bool reduced = false) {
|
||||||
cube<R> c(kd,reduced);
|
cube<R> c (kd, reduced);
|
||||||
ptr<const module<R> > C = c.khC;
|
ptr<const module<R> > C = c.khC;
|
||||||
mod_map<R> d = c.compute_d(1, 0, 0, 0, 0);
|
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));
|
|
||||||
|
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;
|
C = s.new_C;
|
||||||
d = s.new_d;
|
d = s.new_d;
|
||||||
multivariate_laurentpoly<Z> khp;
|
return C->free_poincare_polynomial();
|
||||||
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);
|
template<class R>
|
||||||
multivariate_laurentpoly<Z> p2 = multivariate_laurentpoly<Z>(1, VARIABLE, 1, gr.q);
|
int compute_s_inv(knot_diagram& kd) {
|
||||||
multivariate_laurentpoly<Z> p3 = p1 * p2;
|
unsigned m = kd.num_components ();
|
||||||
khp += p3;
|
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
|
template<class R> void
|
||||||
@ -413,48 +503,10 @@ compute_invariant ()
|
|||||||
tex_footer ();
|
tex_footer ();
|
||||||
}
|
}
|
||||||
else if (!strcmp (invariant, "s"))
|
else if (!strcmp (invariant, "s"))
|
||||||
{
|
{
|
||||||
unsigned m = kd.num_components ();
|
int s = compute_s_inv<R>(kd);
|
||||||
if (m != 1)
|
fprintf (outfp, "s(%s; %s) = %d\n", knot, field, s);
|
||||||
{
|
}
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf (stderr, "error: unknown invariant %s\n", invariant);
|
fprintf (stderr, "error: unknown invariant %s\n", invariant);
|
||||||
@ -753,14 +805,14 @@ main (int argc, char **argv)
|
|||||||
inv_jones_pol.display_self();
|
inv_jones_pol.display_self();
|
||||||
multivariate_laurentpoly<Z> diff = jones_pol - inv_jones_pol;
|
multivariate_laurentpoly<Z> diff = jones_pol - inv_jones_pol;
|
||||||
diff.display_self();
|
diff.display_self();
|
||||||
check_przytycki_cong(diff, 3);
|
check_przytycki_cong<Z,Zp<5>>(diff, 5);
|
||||||
}
|
}
|
||||||
else if(!strcmp(invariant, "khp")) {
|
else if(!strcmp(invariant, "khp")) {
|
||||||
multivariate_laurentpoly<Z> khp;
|
multivariate_laurentpoly<Z> khp;
|
||||||
if(!strcmp(field, "Z2"))
|
if(!strcmp(field, "Z2"))
|
||||||
khp = compute_khp<Z2>(kd, reduced);
|
khp = compute_khp<Z2>(kd, reduced);
|
||||||
else if(!strcmp(field, "Z3"))
|
else if(!strcmp(field, "Z3"))
|
||||||
khp = compute_khp<Zp<3> >(kd, reduced);
|
khp = compute_khp<Zp<3>>(kd, reduced);
|
||||||
else if(!strcmp(field, "Q"))
|
else if(!strcmp(field, "Q"))
|
||||||
khp = compute_khp<Q>(kd, reduced);
|
khp = compute_khp<Q>(kd, reduced);
|
||||||
else
|
else
|
||||||
@ -771,6 +823,25 @@ main (int argc, char **argv)
|
|||||||
printf("Khovanov polynomial of %s is equal to (coefficients %s):\n", knot, field);
|
printf("Khovanov polynomial of %s is equal to (coefficients %s):\n", knot, field);
|
||||||
khp.display_self();
|
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
|
else
|
||||||
{
|
{
|
||||||
if (!strcmp (field, "Z2"))
|
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