jeanluct / braidlab

Matlab package for analyzing data using braids
GNU General Public License v3.0
24 stars 10 forks source link

Implement Lawrence-Krammer representation #10

Closed jeanluct closed 9 years ago

jeanluct commented 9 years ago

This is not so necessary, but could be fun. I've already done this in Mathematica somewhere (Braid.m, I think), so dig up the code first. But first solve issue #9, so that the LK rep can also have polynomial entries.

jeanluct commented 9 years ago

From Jean-Luc Thiffeault on 2014-02-15 21:53:53+00:00

Here's Mathematica code that generates the matrices of the representation:

#!mathematica

LawrenceKrammerRepresentation[n_,t_,q_] := Module[
    {nn = n(n-1)/2, b, v, sig},

    v = Flatten[Table[{j, k}, {j, 1, n-1}, {k, j+1, n}], 1];

    sig[i_, {j_, k_}, {j_, k_}] := 1 /; i != j - 1 && i != j && i != k - 1 && i != k;
    sig[i_, {j_, k_}, {i_, k_}] := q /; i == j - 1;
    sig[i_, {j_, k_}, {i_, j_}] := (q^2 - q) /; i == j - 1;
    sig[i_, {j_, k_}, {j_, k_}] := (1 - q) /; i == j - 1;
    sig[i_, {j_, k_}, {l_, k_}] := 1 /; i == j && j != k - 1 && l == j + 1;
    sig[i_, {j_, k_}, {j_, i_}] := q /; i == k - 1 && k - 1 != j;
    sig[i_, {j_, k_}, {j_, k_}] := (1 - q) /; i == k - 1 && k - 1 != j;
    sig[i_, {j_, k_}, {i_, k_}] := -(q^2 - q) t /; i == k - 1 && k - 1 != j;
    sig[i_, {j_, k_}, {j_, l_}] := 1 /; i == k && l == k + 1;
    sig[i_, {j_, k_}, {j_, k_}] := -t q^2 /; i == j && j == k - 1;
    sig[i_, {j1_, k1_}, {j2_, k2_}] := 0;

    If[n > 2,
        b = Table[sig[i, v[[j]], v[[k]]], {i, n-1}, {j,nn}, {k,nn}];
        Return[b]
    ,
        Return[{{{1}}}]
    ];
]

This works (checked it), but is a bit opaque. It might be hard to do the multiplication sparsely. I guess first implement it densely and figure out the sparsity, the way I did in braidrep.hpp?

jeanluct commented 9 years ago

From Jean-Luc Thiffeault on 2014-02-15 22:06:51+00:00

Here's C++ code that also does it (from braidrep.hpp):

#!C++

template<class T>
void braidrep_dense_LawrenceKrammer<T>::fill_generators()
{
  if (n == 2)
    {
      Mgen[0](0,0) = -q*q*t;
      Mgeninv[0](0,0) = 1./Mgen[0](0,0);
    }
  else
    {
      // Make an index of the basis of the module.
      jlt::mathmatrix<int> v(n-1,n);
      int idx = 0;
      for (unsigned int j = 0; j < n-1; ++j)
        {
          for (unsigned int k = j+1; k < n; ++k)
            {
              v(j,k) = idx++;
            }
        }

      // Fill matrices with the Lawrence-Krammer representation.
      // Messy code, but it is easy to check that it works fine with
      // the check_representation() member function.
      for (unsigned int i = 0; i < n-1; ++i)
        {
          for (unsigned int j1 = 0; j1 < n-1; ++j1)
            {
              for (unsigned int k1 = j1+1; k1 < n; ++k1)
                {
                  for (unsigned int j2 = 0; j2 < n-1; ++j2)
                    {
                      for (unsigned int k2 = j2+1; k2 < n; ++k2)
                        {
                          std::complex<T> el;
                          if (j1 == j2 && k1 == k2 && i != j1-1 &&
                              i != j1 && i != k1 && i != k1-1)
                            {
                              el = 1.;
                            }
                          else if (i == j2 && k1 == k2 && i == j1-1)
                            {
                              el = q;
                            }
                          else if (j2 == i && k2 == j1 && i == j1-1)
                            {
                              el = q*(q-1.);
                            }
                          else if (j1 == j2 && k1 == k2 && i == j1-1)
                            {
                              el = 1.-q;
                            }
                          else if (k1 == k2 && i == j1 && 
                                   j1 != k1-1 && j2 == j1+1)
                            {
                              el = 1.;
                            }
                          else if (i == k2 && j1 == j2 &&
                                   i == k1-1 && j1 != k1-1)
                            {
                              el = q;
                            }
                          else if (i == k1-1 && j1 != k1-1 &&
                                   j1 == j2 && k1 == k2)
                            {
                              el = 1.-q;
                            }
                          else if (i == k1-1 && j1 != k1-1 &&
                                   i == j2 && k1 == k2)
                            {
                              el = -q*(q-1.)*t;
                            }
                          else if (j1 == j2 && i == k1 && k2 == k1+1)
                            {
                              el = 1.;
                            }
                          else if (j1 == j2 && k1 == k2 &&
                                   i == j1 && j1 == k1-1)
                            {
                              el = -t*q*q;
                            }
                          else
                            {
                              el = 0.;
                            }
                          Mgen[i](v(j1,k1),v(j2,k2)) = el;
                        }
                    }
                }
            }
          Mgeninv[i] = Mgen[i].inverse();
        }
    }
}
jeanluct commented 9 years ago

From Jean-Luc Thiffeault on 2014-02-15 22:08:34+00:00

There is actually another obstacle to implementing this: even though laurpoly was used for the Burau representation, would need two-variables Laurent polynomial. Use symbolic toolbox? It's going to be slow...

jeanluct commented 9 years ago

From Jean-Luc Thiffeault on 2014-02-16 22:30:10+00:00

Adapted Burau rep to the symbolic toolbox in df454d5e. It's slow, but could do the same for LK.

jeanluct commented 9 years ago

Implemented in 9b6e11a on branch iss010-lk-rep.

jeanluct commented 9 years ago

It works ok for now. Pretty slow.