Virasoro algebra

Virasoro algebra is the central extension of a Lie algebra with wide applications in the two-dimensional conformal field theory. Its generators \(L_n, n \in \mathbb{Z}\) satisfy commutation relations

\[[L_m, L_n] = (m - n) L_{m+n} + c(m^3 - m) \delta_{m, -n},\]

where \(c\) is the central charge commuting with all generators. It was shown in [FNZ88] that the Virasoro algebra can be constructed out of just two generators \(L_3\) and \(L_{-2}\) using the following recurrence relations,

\[\begin{split}\begin{align} L_1 &= \frac{1}{5}[L_3, L_{-2}],\\ L_{-1} &= \frac{1}{3}[L_1, L_{-2}],\\ L_2 &= \frac{1}{4}[L_3, L_{-1}],\\ L_0 &= \frac{1}{2}[L_1, L_{-1}],\\ L_{n+1} &= \frac{1}{n-1}[L_n, L_1] \text{ for } n>2,\\ L_{-n-1} &= \frac{1}{1-n}[L_{-n}, L_{-1}] \text{ for } n>1. \end{align}\end{split}\]

In the example below, we show how to implement the Virasoro algebra in libcommute’s framework and use it to verify the recurrence relations stated above.

  1#include <iostream>
  2#include <memory>
  3#include <tuple>
  4
  5#include <libcommute/libcommute.hpp>
  6
  7namespace libcommute {
  8
  9// Define a new generator type by deriving from the abstract base class
 10// 'libcommute::generator<IndexTypes...>'. Generators of the Virasoro algebra
 11// L_n carry one integer index 'n'.
 12// Canonical order of generators in a monomial L_n * L_m * L_k * ... is such
 13// that n < m < k < ...
 14class generator_virasoro : public generator<int> {
 15
 16  using base = generator<int>;
 17  using linear_function_t = typename base::linear_function_t;
 18
 19  // For the sake of simplicity, we fix the central charge once and for all.
 20  static constexpr double central_charge = 2.0;
 21
 22public:
 23  // This function must return a unique algebra ID shared by all generators
 24  // of a particular algebra.
 25  int algebra_id() const override {
 26    // Use the lowest algebra ID available to user-defined algebras
 27    return min_user_defined_algebra_id;
 28  }
 29
 30  // Construct generator with a given index 'n'
 31  explicit generator_virasoro(int n) : base(n) {}
 32  // Standard constructors and destructor
 33  generator_virasoro(generator_virasoro const&) = default;
 34  generator_virasoro(generator_virasoro&&) noexcept = default;
 35  ~generator_virasoro() override = default;
 36
 37  // Generator objects must be immutable
 38  generator_virasoro& operator=(generator_virasoro const&) = delete;
 39  generator_virasoro& operator=(generator_virasoro&&) noexcept = delete;
 40
 41  // Given a product L_m * L_n with m > n, transform it to the canonically
 42  // ordered form L_n * L_m plus some linear function of generators.
 43  // For the Virasoro algebra the transformation is
 44  //
 45  // L_m * L_n -> L_n * L_m + (m-n)*L_{m+n} + c(m^3 - m)\delta(m,-n)
 46  //
 47  // L_m will be passed to swap_with() as *this, i.e. L_m.swap_with(L_n, f).
 48  var_number swap_with(base const& L_n, linear_function_t& f) const override {
 49    // Ensure that L_m > L_n, or equivalently m > n.
 50    assert(*this > L_n);
 51
 52    auto const& L_n_ = dynamic_cast<generator_virasoro const&>(L_n);
 53
 54    // Extract indices from L_m and L_n
 55    int m = std::get<0>(base::indices());
 56    int n = std::get<0>(L_n_.indices());
 57
 58    // Write linear terms of the transformed expressions into 'f'
 59    f.set(m == -n ? (central_charge * (m * m * m - m)) : 0, // Constant term
 60          std::make_shared<generator_virasoro>(m + n),      // L_{m+n}
 61          m - n // Coefficient in front of L_{m+n}
 62    );
 63
 64    // Return coefficient in front of L_n * L_m in the transformed expression
 65    return 1;
 66  }
 67
 68  // Given a product L_m * L_n with m <= n, optionally transform it to
 69  // some linear function of generators. For the Virasoro algebra such a
 70  // transformation exists for L_m = L_n,
 71  //
 72  // L_m * L_n -> 0
 73  //
 74  // L_m will be passed to simplify_prod() as *this,
 75  // i.e. L_m.simplify_prod(L_n, f).
 76  bool simplify_prod(base const& L_n, linear_function_t& f) const override {
 77    // Ensure that L_m <= L_n, or equivalently m <= n.
 78    assert(!(*this > L_n));
 79
 80    if(*this == L_n) {
 81      // The transformed product is identically zero
 82      f.set(0);
 83      return true;
 84    } else
 85      return false; // No suitable transformation can be applied
 86  }
 87
 88  // Hermitian conjugate: (L_n)^\dagger = L_{-n}
 89  void conj(linear_function_t& f) const override {
 90    int conj_n = -std::get<0>(base::indices());
 91    f.set(0, std::make_shared<generator_virasoro>(conj_n), 1);
 92  }
 93
 94  // String representation of L_n
 95  std::string to_string() const override {
 96    int n = std::get<0>(base::indices());
 97    return "L(" + std::to_string(n) + ")";
 98  }
 99};
100
101// Convenience factory function to create expressions made of one
102// monomial L_n.
103expression<double, int> L(int n) {
104  using ret_t = expression<double, int>;
105  return ret_t(1.0, ret_t::monomial_t(generator_virasoro(n)));
106}
107
108} // namespace libcommute
109
110using namespace libcommute;
111
112int main() {
113
114  // Check that L(0) is Hermitian and (L_n)^\dagger = L_{-n}
115  std::cout << "conj(L(0)) = " << conj(L(0)) << '\n';
116  std::cout << "conj(L(1)) = " << conj(L(1)) << '\n';
117
118  // Check that L(n)^2 = 0 for a few n
119  std::cout << "L(0) * L(0) = " << L(0) * L(0) << '\n';
120  std::cout << "L(1) * L(1) = " << L(1) * L(1) << '\n';
121  std::cout << "L(-1) * L(-1) = " << L(-1) * L(-1) << '\n';
122
123  // Check recurrence relations from Eq. (5)
124  std::cout << "L_1 - (1/5)[L_3, L_{-2}] = "
125            << (L(1) - (1.0 / 5) * (L(3) * L(-2) - L(-2) * L(3))) << '\n';
126  std::cout << "L_{-1} - (1/3)[L_1, L_{-2}] = "
127            << (L(-1) - (1.0 / 3) * (L(1) * L(-2) - L(-2) * L(1))) << '\n';
128  std::cout << "L_2 - (1/4)[L_3, L_{-1}] = "
129            << (L(2) - (1.0 / 4) * (L(3) * L(-1) - L(-1) * L(3))) << '\n';
130  std::cout << "L_0 - (1/2)[L_1, L_{-1}] = "
131            << (L(0) - (1.0 / 2) * (L(1) * L(-1) - L(-1) * L(1))) << '\n';
132
133  // Check recurrence relation Eq. (6) for some higher positive n
134  for(int n = 3; n < 10; ++n) {
135    std::cout << "L_" << (n + 1) << " - (1/" << (n - 1) << ")"
136              << "[L_" << n << ", L_1] = "
137              << (L(n + 1) - (1.0 / (n - 1)) * (L(n) * L(1) - L(1) * L(n)))
138              << '\n';
139  }
140  // Check recurrence relation Eq. (7) for some higher negative n
141  for(int n = 2; n < 10; ++n) {
142    std::cout << "L_" << (-n - 1) << " - (1/(" << (1 - n) << "))"
143              << "[L_" << -n << ", L_{-1}] = "
144              << (L(-n - 1) - (1.0 / (1 - n)) * (L(-n) * L(-1) - L(-1) * L(-n)))
145              << '\n';
146  }
147
148  return 0;
149}
[FNZ88]

“A presentation for the Virasoro and super-Virasoro algebras”, D. B. Fairlie, J. Nuyts and C. K. Zachos , Commun. Math. Phys. 117, pp. 595–614 (1988), https://doi.org/10.1007/BF01218387