knotkit/algebra/linear_combination.h
Wojciech Politarczyk 203477c3a8 First shot at periodicity congruences
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.
2016-11-24 15:28:31 +01:00

518 lines
12 KiB
C++

#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
{
private:
// friend class linear_combination_iter<R>;
friend class linear_combination_const_iter<R>;
friend class module<R>;
friend class free_submodule<R>;
friend class quotient_module<R>;
friend class mod_map<R>;
typedef module<R> Rmod;
public:
// typedef linear_combination_iter<R> iter;
typedef linear_combination_const_iter<R> const_iter;
private:
ptr<const Rmod> m;
map<unsigned, R> v;
public:
linear_combination () { }
explicit linear_combination (ptr<const Rmod> m_) : m(m_) { }
linear_combination (ptr<const Rmod> m_, int x)
: m(m_)
{
assert (x == 0);
}
linear_combination (const linear_combination &lc) : m(lc.m), v(lc.v) { }
linear_combination (copy, const linear_combination &lc)
: m(lc.m)
{
for (typename map<unsigned, R>::const_iter i = lc.v; i; i ++)
v.push (i.key (), R (COPY, i.val ()));
}
linear_combination (reader &r)
{
m = r.read_mod<R> ();
v = map<unsigned, R> (r);
}
~linear_combination () { }
linear_combination &operator = (const linear_combination &lc)
{
m = lc.m;
v = lc.v;
return *this;
}
bool operator == (const linear_combination &lc2) const
{
assert (m == lc2.m);
linear_combination lc3 (COPY, *this);
lc3 -= lc2;
return lc3 == 0;
}
bool operator != (const linear_combination &lc) const { return !operator == (lc); }
bool operator == (int x) const
{
assert (x == 0);
#ifndef NDEBUG
check ();
#endif
return v.is_empty ();
}
bool operator != (int x) const { return !operator == (x); }
bool homogeneous () const
{
if (v.is_empty ())
return 1;
pair<unsigned, R> p = v.head ();
grading hq = m->generator_grading (p.first);
for (typename map<unsigned, R>::const_iter i = v; i; i ++)
{
if (hq != m->generator_grading (i.key ()))
return 0;
}
return 1;
}
pair<unsigned, R> head () const { return v.head (); }
grading hq () const
{
// assert (homogeneous ());
pair<unsigned, R> p = v.head ();
return m->generator_grading (p.first);
}
R annihilator () const;
void set_coeff (R c, unsigned i)
{
if (c == 0)
v -= i;
else
v[i] = c;
}
linear_combination operator * (R c) const
{
linear_combination r (COPY, *this);
r *= c;
return r;
}
linear_combination operator + (const linear_combination &lc) const
{
linear_combination r (COPY, *this);
r += lc;
return r;
}
linear_combination operator - (const linear_combination &lc) const
{
linear_combination r (COPY, *this);
r -= lc;
return r;
}
linear_combination &operator += (unsigned i) { return muladd (1, i); }
linear_combination &operator -= (unsigned i) { return mulsub (1, i); }
linear_combination &operator *= (R c);
linear_combination &operator /= (R c);
linear_combination &operator += (const linear_combination &lc);
linear_combination &operator -= (const linear_combination &lc);
linear_combination &muladd (R c, unsigned i);
linear_combination &muladd (R c, const linear_combination &lc);
linear_combination &mulsub (R c, unsigned i);
linear_combination &mulsub (R c, const linear_combination &lc);
void yank (unsigned i) { v.yank (i); }
void clear () { v.clear (); }
bool operator % (unsigned i) const { return v % i; }
R operator () (unsigned i) const { return v(i, R (0)); }
unsigned card () const { return v.card (); }
linear_combination<R> tensor (const linear_combination<R> &lc) const
{
linear_combination<R> r (m->tensor (lc.m));
for (linear_combination_const_iter<R> i = *this; i; i ++)
for (linear_combination_const_iter<R> j = lc; j; j ++)
{
r.muladd (i.val () * j.val (), m->tensor_generators (i.key (), lc.m, j.key ()));
}
return r;
}
#ifndef NDEBUG
void check () const
{
for (typename map<unsigned, R>::const_iter i = v; i; i ++)
assert (!m->is_zero (i.val (), i.key ()));
}
#endif
void write_self (writer &w) const
{
write (w, *m);
write (w, v);
}
void show_self () const;
void display_self () const { show_self (); newline (); }
};
template<class R> linear_combination<R>
operator * (R c, const linear_combination<R> &lc)
{
return lc * c;
}
template<class R>
class linear_combination_const_iter
{
typename map<unsigned, R>::const_iter i;
public:
linear_combination_const_iter (const linear_combination<R> &lc) : i(lc.v) { }
~linear_combination_const_iter () { }
operator bool () const { return i; }
linear_combination_const_iter &operator ++ () { i ++; return *this; }
void operator ++ (int) { i ++; }
unsigned key () const { return i.key (); }
R val () { return i.val (); }
};
template<class R> R
linear_combination<R>::annihilator () const
{
R r (1);
for (typename map<unsigned, R>::const_iter i = v; i; i ++)
r = r.lcm (m->annihilator (i.val (), i.key ()));
return r;
}
template<class R> linear_combination<R> &
linear_combination<R>::operator *= (R c)
{
if (c == 0)
v.clear ();
else if (c != 1)
{
for (typename map<unsigned, R>::iter i = v; i; i ++)
i.val () *= c;
}
return *this;
}
template<class R> linear_combination<R> &
linear_combination<R>::operator += (const linear_combination &lc)
{
assert (m == lc.m);
for (typename map<unsigned, R>::const_iter i = lc.v; i; i ++)
{
unsigned k = i.key ();
R &c = v[k];
c += i.val ();
if (m->is_zero (c, k))
v -= k;
}
return *this;
}
template<class R> linear_combination<R> &
linear_combination<R>::operator -= (const linear_combination &lc)
{
assert (m == lc.m);
for (typename map<unsigned, R>::const_iter i = lc.v; i; i ++)
{
unsigned k = i.key ();
R &c = v[k];
c -= i.val ();
if (m->is_zero (c, k))
v -= k;
}
return *this;
}
template<class R> linear_combination<R> &
linear_combination<R>::muladd (R c, unsigned i)
{
R &ic = v[i];
ic += c;
if (m->is_zero (ic, i))
v -= i;
return *this;
}
template<class R> linear_combination<R> &
linear_combination<R>::muladd (R c, const linear_combination &lc)
{
assert (m == lc.m);
for (typename map<unsigned, R>::const_iter i = lc.v; i; i ++)
{
unsigned k = i.key ();
R &vc = v[k];
vc += (c * i.val ());
if (vc == 0)
v -= k;
}
return *this;
}
template<class R> linear_combination<R> &
linear_combination<R>::mulsub (R c, unsigned i)
{
R &ic = v[i];
ic -= c;
if (m->is_zero (ic, i))
v -= i;
return *this;
}
template<class R> linear_combination<R> &
linear_combination<R>::mulsub (R c, const linear_combination &lc)
{
assert (m == lc.m);
for (typename map<unsigned, R>::const_iter i = lc.v; i; i ++)
{
unsigned k = i.key ();
R &vc = v[k];
vc -= (c * i.val ());
if (vc == 0)
v -= k;
}
return *this;
}
template<class R> void
linear_combination<R>::show_self () const
{
bool first = 1;
for (typename map<unsigned, R>::const_iter i = v; i; i ++)
{
if (first)
first = 0;
else
printf (" + ");
show (i.val ());
// printf ("*%d", i.key ());
printf ("*");
m->show_generator (i.key ());
}
}
template<>
class linear_combination<Z2>
{
private:
// friend class linear_combination_iter<Z2>;
friend class linear_combination_const_iter<Z2>;
friend class module<Z2>;
friend class free_submodule<Z2>;
friend class quotient_module<Z2>;
friend class mod_map<Z2>;
typedef module<Z2> Z2mod;
public:
typedef linear_combination_const_iter<Z2> const_iter;
private:
ptr<const Z2mod> m;
set<unsigned> v;
public:
linear_combination () { }
linear_combination (ptr<const Z2mod> m_) : m(m_) { }
linear_combination (const linear_combination &lc) : m(lc.m), v(lc.v) { }
linear_combination (copy, const linear_combination &lc) : m(lc.m), v(COPY, lc.v) { }
linear_combination (reader &r)
{
m = r.read_mod<Z2> ();
v = set<unsigned> (r);
}
~linear_combination () { }
linear_combination &operator = (const linear_combination &lc)
{
m = lc.m;
v = lc.v;
return *this;
}
bool operator == (const linear_combination &lc) const { assert (m == lc.m); return v == lc.v; }
bool operator != (const linear_combination &lc) const { return !operator == (lc); }
bool operator == (int x) const { assert (x == 0); return v.is_empty (); }
bool operator != (int x) const { return !operator == (x); }
pair<unsigned, Z2> head () const { return pair<unsigned, Z2> (v.head (), Z2 (1)); }
grading hq () const
{
// assert (homogeneous ());
return m->generator_grading (v.head ());
}
Z2 annihilator () const
{
return Z2 (operator == (0) ? 1 : 0);
}
void set_coeff (Z2 c, unsigned i)
{
if (c == 0)
v -= i;
else
v += i;
}
linear_combination operator * (Z2 c) const
{
if (c == 1)
return *this;
else
return linear_combination (m);
}
linear_combination operator + (const linear_combination &lc) const
{
linear_combination r (COPY, *this);
r += lc;
return r;
}
linear_combination operator - (const linear_combination &lc) const
{
linear_combination r (COPY, *this);
r -= lc;
return r;
}
linear_combination &operator *= (Z2 c)
{
if (c == 0)
v.clear ();
return *this;
}
linear_combination &operator /= (Z2 c) { assert (c == 1); return *this; }
linear_combination &operator += (unsigned i) { v.toggle (i); return *this; }
linear_combination &operator -= (unsigned i) { v.toggle (i); return *this; }
linear_combination &muladd (Z2 c, unsigned i)
{
if (c == 1)
operator += (i);
return *this;
}
linear_combination &mulsub (Z2 c, unsigned i)
{
if (c == 1)
operator -= (i);
return *this;
}
linear_combination &operator += (const linear_combination &lc) { v ^= lc.v; return *this; }
linear_combination &operator -= (const linear_combination &lc) { v ^= lc.v; return *this; }
linear_combination &muladd (Z2 c, const linear_combination &lc)
{
if (c == 1)
operator += (lc);
return *this;
}
linear_combination &mulsub (Z2 c, const linear_combination &lc)
{
if (c == 1)
operator -= (lc);
return *this;
}
void yank (unsigned i) { v.yank (i); }
void clear () { v.clear (); }
bool operator % (unsigned i) const { return v % i; }
Z2 operator () (unsigned i) const { return Z2 (v % i); }
unsigned card () const { return v.card (); }
#ifndef NDEBUG
void check () const;
#endif
void write_self (writer &w) const
{
write (w, *m);
write (w, v);
}
void show_self () const;
void display_self () const { show_self (); newline (); }
};
inline void
linear_combination<Z2>::show_self () const
{
bool first = 1;
for (set_const_iter<unsigned> i = v; i; i ++)
{
if (first)
first = 0;
else
printf ("+");
// printf ("%d", i.val ());
m->show_generator (i.val ());
}
}
inline linear_combination<Z2>
operator * (Z2 c, const linear_combination<Z2> &lc)
{
return lc * c;
}
template<>
class linear_combination_const_iter<Z2>
{
set<unsigned>::const_iter i;
public:
linear_combination_const_iter (const linear_combination<Z2> &lc) : i(lc.v) { }
~linear_combination_const_iter () { }
operator bool () const { return i; }
linear_combination_const_iter &operator ++ () { i ++; return *this; }
void operator ++ (int) { i ++; }
unsigned key () const { return i.val (); }
Z2 val () { return Z2 (1); }
};
#endif // _KNOTKIT_ALGEBRA_LINEAR_COMBINATIONS_H