203477c3a8
Verification of Przytycki's congruence works fine, however there are some small modifications that could be made. The, naive, approach to the verification of periodicity congruence for the Khovanov polynomial didn't work. There are just too many cases to check. Generation of all of them can exhaust the memory.
505 lines
11 KiB
C++
505 lines
11 KiB
C++
#ifndef _KNOTKIT_ALGEBRA_MULTIVARIATE_POLYNOMIAL_H
|
|
#define _KNOTKIT_ALGEBRA_MULTIVARIATE_POLYNOMIAL_H
|
|
/* multivariate polynomial in a (vector) variable x with coefficients
|
|
in T. */
|
|
|
|
template<unsigned n>
|
|
class multivariate_monomial
|
|
{
|
|
public:
|
|
unsigned v[n];
|
|
|
|
public:
|
|
multivariate_monomial ()
|
|
{
|
|
for (unsigned i = 0; i < n; i ++)
|
|
v[i] = 0;
|
|
}
|
|
|
|
multivariate_monomial (variable, unsigned j)
|
|
{
|
|
for (unsigned i = 0; i < n; i ++)
|
|
v[i] = 0;
|
|
|
|
assert (j >= 1 && j <= n);
|
|
v[j - 1] = 1;
|
|
}
|
|
|
|
multivariate_monomial (const multivariate_monomial &e)
|
|
{
|
|
for (unsigned i = 0; i < n; i ++)
|
|
v[i] = e.v[i];
|
|
}
|
|
|
|
~multivariate_monomial () { }
|
|
|
|
multivariate_monomial &operator = (const multivariate_monomial &e)
|
|
{
|
|
for (unsigned i = 0; i < n; i ++)
|
|
v[i] = e.v[i];
|
|
return *this;
|
|
}
|
|
|
|
unsigned degree () const
|
|
{
|
|
unsigned d = 0;
|
|
for (unsigned i = 0; i < n; i ++)
|
|
d += v[i];
|
|
return d;
|
|
}
|
|
|
|
bool operator == (const multivariate_monomial &e) const
|
|
{
|
|
for (unsigned i = 0; i < n; i ++)
|
|
{
|
|
if (v[i] != e.v[i])
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
bool operator != (const multivariate_monomial &e) const { return !operator == (e); }
|
|
|
|
bool operator < (const multivariate_monomial &e) const
|
|
{
|
|
for (unsigned i = 0; i < n; i ++)
|
|
{
|
|
if (v[i] < e.v[i])
|
|
return 1;
|
|
if (v[i] > e.v[i])
|
|
return 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
multivariate_monomial operator + (const multivariate_monomial &e) const
|
|
{
|
|
multivariate_monomial m;
|
|
|
|
for (unsigned i = 0; i < n; i ++)
|
|
m.v[i] = v[i] + e.v[i];
|
|
|
|
return m;
|
|
}
|
|
|
|
bool divides (const multivariate_monomial &num) const
|
|
{
|
|
for (unsigned i = 0; i < n; i ++)
|
|
{
|
|
if (v[i] > num.v[i])
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
bool operator | (const multivariate_monomial &num) const { return divides (num); }
|
|
|
|
multivariate_monomial &mineq (const multivariate_monomial &e)
|
|
{
|
|
for (unsigned i = 0; i < n; i ++)
|
|
{
|
|
if (e.v[i] < v[i])
|
|
v[i] = e.v[i];
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
multivariate_monomial operator - (const multivariate_monomial &denom) const
|
|
{
|
|
multivariate_monomial m;
|
|
|
|
for (unsigned i = 0; i < n; i ++)
|
|
{
|
|
assert (v[i] >= denom.v[i]);
|
|
m.v[i] = v[i] - denom.v[i];
|
|
}
|
|
|
|
return m;
|
|
}
|
|
|
|
void show_self () const
|
|
{
|
|
printf ("x^(");
|
|
for (unsigned i = 0; i < n; i ++)
|
|
{
|
|
if (i > 0)
|
|
printf (",");
|
|
printf ("%d", v[i]);
|
|
}
|
|
printf (")");
|
|
}
|
|
};
|
|
|
|
template<class T, unsigned n>
|
|
class multivariate_polynomial
|
|
{
|
|
public:
|
|
typedef ::linear_combination<multivariate_polynomial<T, n> > linear_combination;
|
|
typedef ::linear_combination_const_iter<multivariate_polynomial<T, n> >
|
|
linear_combination_const_iter;
|
|
|
|
private:
|
|
typedef multivariate_monomial<n> monomial;
|
|
|
|
map<monomial, T> coeffs;
|
|
|
|
explicit multivariate_polynomial (const map<monomial, T> &coeffs_) : coeffs(coeffs_) { }
|
|
|
|
public:
|
|
multivariate_polynomial () { }
|
|
multivariate_polynomial (int x)
|
|
{
|
|
T c (x);
|
|
if (c != 0)
|
|
coeffs.push (monomial (), c);
|
|
}
|
|
|
|
multivariate_polynomial (T c)
|
|
{
|
|
if (c != 0)
|
|
coeffs.push (monomial (), c);
|
|
}
|
|
|
|
multivariate_polynomial (T c, variable, unsigned i)
|
|
{
|
|
if (c != 0)
|
|
coeffs.push (monomial (VARIABLE, i), c);
|
|
}
|
|
|
|
multivariate_polynomial (T c, const monomial &m)
|
|
{
|
|
if (c != 0)
|
|
coeffs.push (m, c);
|
|
}
|
|
|
|
multivariate_polynomial (const multivariate_polynomial &p) : coeffs(p.coeffs) { }
|
|
multivariate_polynomial (copy, const multivariate_polynomial &p) : coeffs(COPY, p.coeffs) { }
|
|
~multivariate_polynomial () { }
|
|
|
|
multivariate_polynomial &operator = (const multivariate_polynomial &p)
|
|
{
|
|
coeffs = p.coeffs;
|
|
return *this;
|
|
}
|
|
|
|
multivariate_polynomial &operator = (int x)
|
|
{
|
|
coeffs = map<monomial, T> ();
|
|
T c (x);
|
|
if (c != 0)
|
|
coeffs.push (monomial (), c);
|
|
return *this;
|
|
}
|
|
|
|
multivariate_polynomial &operator = (T c)
|
|
{
|
|
coeffs = map<monomial, T> ();
|
|
if (c != 0)
|
|
coeffs.push (monomial (), c);
|
|
return *this;
|
|
}
|
|
|
|
bool is_unit () const;
|
|
|
|
bool operator == (const multivariate_polynomial &p) const
|
|
{
|
|
#ifndef NDEBUG
|
|
check ();
|
|
p.check ();
|
|
#endif
|
|
return coeffs == p.coeffs;
|
|
}
|
|
bool operator != (const multivariate_polynomial &p) const { return !operator == (p); }
|
|
|
|
bool operator == (int x) const
|
|
{
|
|
#ifndef NDEBUG
|
|
check ();
|
|
#endif
|
|
T c (x);
|
|
if (c == 0)
|
|
return coeffs.is_empty ();
|
|
else
|
|
{
|
|
if (coeffs.card () != 1)
|
|
return 0;
|
|
|
|
pair<monomial, T> p = coeffs.head ();
|
|
return p.first.degree () == 0
|
|
&& p.second == c;
|
|
}
|
|
}
|
|
|
|
bool operator != (int x) const { return !operator == (x); }
|
|
|
|
multivariate_polynomial &operator += (multivariate_polynomial p);
|
|
multivariate_polynomial &operator -= (multivariate_polynomial p);
|
|
multivariate_polynomial &operator *= (multivariate_polynomial p) { return operator = (*this * p); }
|
|
multivariate_polynomial &operator *= (T s);
|
|
|
|
multivariate_polynomial &add_term (T c, variable, unsigned i)
|
|
{
|
|
monomial m (VARIABLE, i);
|
|
T &c2 = coeffs[m];
|
|
c2 += c;
|
|
if (c2 == 0)
|
|
coeffs -= m;
|
|
return *this;
|
|
}
|
|
|
|
multivariate_polynomial operator - () const { return multivariate_polynomial () - *this; }
|
|
multivariate_polynomial operator + (multivariate_polynomial p) const
|
|
{
|
|
multivariate_polynomial r (COPY, *this);
|
|
r += p;
|
|
return r;
|
|
}
|
|
|
|
multivariate_polynomial operator - (multivariate_polynomial p) const
|
|
{
|
|
multivariate_polynomial r (COPY, *this);
|
|
r -= p;
|
|
return r;
|
|
}
|
|
|
|
multivariate_polynomial operator * (const multivariate_polynomial &p) const;
|
|
|
|
monomial common_monomial () const;
|
|
|
|
multivariate_polynomial gcd (const multivariate_polynomial &b) const
|
|
{
|
|
// ???
|
|
return multivariate_polynomial (1);
|
|
}
|
|
|
|
pair<multivariate_polynomial, multivariate_polynomial>
|
|
uncommon_factors (multivariate_polynomial b, basedvector<multivariate_polynomial, 1> ds);
|
|
maybe<multivariate_polynomial>
|
|
divides_exactly (const multivariate_polynomial &num) const;
|
|
multivariate_polynomial divide_exact (const multivariate_polynomial &d) const;
|
|
|
|
bool operator | (const multivariate_polynomial &num) const { abort (); }
|
|
|
|
#ifndef NDEBUG
|
|
void check () const;
|
|
#endif
|
|
|
|
static void show_ring ()
|
|
{
|
|
T::show_ring ();
|
|
switch (n)
|
|
{
|
|
case 0: break;
|
|
case 1: printf ("[x_1]"); break;
|
|
case 2: printf ("[x_1, x_2]"); break;
|
|
default:
|
|
printf ("[x_1, ..., x_%d]", n);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void display_self () const { show_self (); newline (); }
|
|
void show_self () const;
|
|
};
|
|
|
|
template<class T, unsigned n> bool
|
|
multivariate_polynomial<T, n>::is_unit () const
|
|
{
|
|
// ??? is_singleton
|
|
if (coeffs.card () != 1)
|
|
return 0;
|
|
|
|
pair<monomial, T> p = coeffs.head ();
|
|
return p.first.degree () == 0
|
|
&& p.second.is_unit ();
|
|
}
|
|
|
|
template<class T, unsigned n> multivariate_polynomial<T, n> &
|
|
multivariate_polynomial<T, n>::operator += (multivariate_polynomial p)
|
|
{
|
|
for (typename map<monomial, T>::const_iter i = p.coeffs; i; i ++)
|
|
{
|
|
monomial m = i.key ();
|
|
T &c = coeffs[m];
|
|
c += i.val ();
|
|
if (c == 0)
|
|
coeffs -= m;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template<class T, unsigned n> multivariate_polynomial<T, n> &
|
|
multivariate_polynomial<T, n>::operator -= (multivariate_polynomial p)
|
|
{
|
|
for (typename map<monomial, T>::const_iter i = p.coeffs; i; i ++)
|
|
{
|
|
monomial m = i.key ();
|
|
T &c = coeffs[m];
|
|
c -= i.val ();
|
|
if (c == 0)
|
|
coeffs -= m;
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
template<class T, unsigned n> multivariate_polynomial<T, n> &
|
|
multivariate_polynomial<T, n>::operator *= (T s)
|
|
{
|
|
if (s == 0)
|
|
coeffs.clear ();
|
|
else
|
|
{
|
|
for (typename map<monomial, T>::iter i = coeffs; i; i ++)
|
|
i.val () *= s;
|
|
}
|
|
}
|
|
|
|
template<class T, unsigned n> multivariate_polynomial<T, n>
|
|
multivariate_polynomial<T, n>::operator * (const multivariate_polynomial &p) const
|
|
{
|
|
multivariate_polynomial r;
|
|
|
|
for (typename map<monomial, T>::const_iter i = coeffs; i; i ++)
|
|
for (typename map<monomial, T>::const_iter j = p.coeffs; j; j ++)
|
|
{
|
|
monomial m = i.key () + j.key ();
|
|
T &c = r.coeffs[m];
|
|
c += i.val () * j.val ();
|
|
if (c == 0)
|
|
r.coeffs -= m;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
template<class T, unsigned n> multivariate_monomial<n>
|
|
multivariate_polynomial<T, n>::common_monomial () const
|
|
{
|
|
monomial m = coeffs.head ().first;
|
|
for (typename map<monomial, T>::const_iter i = coeffs; i; i ++)
|
|
m.mineq (i.key ());
|
|
return m;
|
|
}
|
|
|
|
template<class T, unsigned n> pair<multivariate_polynomial<T, n>,
|
|
multivariate_polynomial<T, n> >
|
|
multivariate_polynomial<T, n>::uncommon_factors (multivariate_polynomial b,
|
|
basedvector<multivariate_polynomial, 1> ds)
|
|
{
|
|
multivariate_polynomial a = *this;
|
|
|
|
monomial m = a.common_monomial ();
|
|
m.mineq (b.common_monomial ());
|
|
|
|
multivariate_polynomial mp (1, m);
|
|
a = a.divide_exact (mp);
|
|
b = b.divide_exact (mp);
|
|
|
|
L:
|
|
for (unsigned i = 1; i <= ds.size (); i ++)
|
|
{
|
|
const multivariate_polynomial &d = ds[i];
|
|
|
|
maybe<multivariate_polynomial> aq = d.divides_exactly (a);
|
|
if (aq.is_some ())
|
|
{
|
|
maybe<multivariate_polynomial> bq = d.divides_exactly (b);
|
|
if (bq.is_some ())
|
|
{
|
|
a = aq.some ();
|
|
b = bq.some ();
|
|
|
|
goto L;
|
|
}
|
|
}
|
|
}
|
|
|
|
return pair<multivariate_polynomial, multivariate_polynomial> (a, b);
|
|
}
|
|
|
|
template<class T, unsigned n> maybe<multivariate_polynomial<T, n> >
|
|
multivariate_polynomial<T, n>::divides_exactly (const multivariate_polynomial &num) const
|
|
{
|
|
const multivariate_polynomial &d = *this;
|
|
|
|
multivariate_polynomial r (COPY, num);
|
|
multivariate_polynomial q;
|
|
|
|
pair<monomial, T> d_leading_term = d.coeffs.tail ();
|
|
for (;;)
|
|
{
|
|
if (r == 0)
|
|
{
|
|
// ??
|
|
assert (q*d == num);
|
|
|
|
return maybe<multivariate_polynomial> (q);
|
|
}
|
|
|
|
pair<monomial, T> r_leading_term = r.coeffs.tail ();
|
|
if (d_leading_term.first | r_leading_term.first)
|
|
{
|
|
multivariate_polynomial m (r_leading_term.second / d_leading_term.second,
|
|
r_leading_term.first - d_leading_term.first);
|
|
r -= m * d;
|
|
q += m;
|
|
}
|
|
else
|
|
return maybe<multivariate_polynomial> ();
|
|
}
|
|
}
|
|
|
|
template<class T, unsigned n> multivariate_polynomial<T, n>
|
|
multivariate_polynomial<T, n>::divide_exact (const multivariate_polynomial &d) const
|
|
{
|
|
maybe<multivariate_polynomial> r = d.divides_exactly (*this);
|
|
return r.some ();
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
template<class T, unsigned n> void
|
|
multivariate_polynomial<T, n>::check () const
|
|
{
|
|
for (typename map<monomial, T>::const_iter i = coeffs; i; i ++)
|
|
assert (i.val () != 0);
|
|
}
|
|
#endif
|
|
|
|
template<class T, unsigned n> void
|
|
multivariate_polynomial<T, n>::show_self () const
|
|
{
|
|
unsigned first = 1;
|
|
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
|
|
printf (" + ");
|
|
|
|
if (m.degree () == 0)
|
|
{
|
|
if (c == 1)
|
|
printf ("1");
|
|
else
|
|
show (c);
|
|
}
|
|
else
|
|
{
|
|
if (c != 1)
|
|
{
|
|
show (c);
|
|
printf ("*");
|
|
}
|
|
show (m);
|
|
}
|
|
}
|
|
if (first)
|
|
printf ("0");
|
|
}
|
|
|
|
#endif // _KNOTKIT_ALGEBRA_MULTIVARIATE_POLYNOMIAL_H
|