# 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, assignments and destructor
33  generator_virasoro(generator_virasoro const&) = default;
34  generator_virasoro(generator_virasoro&&) noexcept = default;
35  generator_virasoro& operator=(generator_virasoro const&) = default;
36  generator_virasoro& operator=(generator_virasoro&&) noexcept = default;
37  ~generator_virasoro() override = default;
38
39  // Virtual copy-constructor: Make a smart pointer managing
40  // a copy of this generator
41  std::unique_ptr<base> clone() const override {
42    return make_unique<generator_virasoro>(*this);
43  }
44
45  // Given a product L_m * L_n with m > n, transform it to the canonically
46  // ordered form L_n * L_m plus some linear function of generators.
47  // For the Virasoro algebra the transformation is
48  //
49  // L_m * L_n -> L_n * L_m + (m-n)*L_{m+n} + c(m^3 - m)\delta(m,-n)
50  //
51  // L_m will be passed to swap_with() as *this, i.e. L_m.swap_with(L_n, f).
52  double swap_with(base const& L_n, linear_function_t& f) const override {
53    // Ensure that L_m > L_n, or equivalently m > n.
54    assert(*this > L_n);
55
56    auto const& L_n_ = dynamic_cast<generator_virasoro const&>(L_n);
57
58    // Extract indices from L_m and L_n
59    int m = std::get<0>(base::indices());
60    int n = std::get<0>(L_n_.indices());
61
62    // Write linear terms of the transformed expressions into 'f'
63    f.set(m == -n ? (central_charge * (m * m * m - m)) : 0, // Constant term
64          make_unique<generator_virasoro>(m + n),           // L_{m+n}
65          m - n // Coefficient in front of L_{m+n}
66    );
67
68    // Return coefficient in front of L_n * L_m in the transformed expression
69    return 1;
70  }
71
72  // Given a product L_m * L_n with m <= n, optionally transform it to
73  // some linear function of generators. For the Virasoro algebra such a
74  // transformation exists for L_m = L_n,
75  //
76  // L_m * L_n -> 0
77  //
78  // L_m will be passed to simplify_prod() as *this,
79  // i.e. L_m.simplify_prod(L_n, f).
80  bool simplify_prod(base const& L_n, linear_function_t& f) const override {
81    // Ensure that L_m <= L_n, or equivalently m <= n.
82    assert(!(*this > L_n));
83
84    if(*this == L_n) {
85      // The transformed product is identically zero
86      f.set(0);
87      return true;
88    } else
89      return false; // No suitable transformation can be applied
90  }
91
92  // Hermitian conjugate: (L_n)^\dagger = L_{-n}
93  void conj(linear_function_t& f) const override {
94    int conj_n = -std::get<0>(base::indices());
95    f.set(0, make_unique<generator_virasoro>(conj_n), 1);
96  }
97
98  // Print L_n to stream
99  std::ostream& print(std::ostream& os) const override {
100    int n = std::get<0>(base::indices());
101    return os << "L(" << n << ")";
102  }
103};
104
105// Convenience factory function to create expressions made of one
106// monomial L_n.
107expression<double, int> L(int n) {
108  using ret_t = expression<double, int>;
109  return ret_t(1.0, ret_t::monomial_t(generator_virasoro(n)));
110}
111
112} // namespace libcommute
113
114using namespace libcommute;
115
116int main() {
117
118  // Check that L(0) is Hermitian and (L_n)^\dagger = L_{-n}
119  std::cout << "conj(L(0)) = " << conj(L(0)) << '\n';
120  std::cout << "conj(L(1)) = " << conj(L(1)) << '\n';
121
122  // Check that L(n)^2 = 0 for a few n
123  std::cout << "L(0) * L(0) = " << L(0) * L(0) << '\n';
124  std::cout << "L(1) * L(1) = " << L(1) * L(1) << '\n';
125  std::cout << "L(-1) * L(-1) = " << L(-1) * L(-1) << '\n';
126
127  // Check recurrence relations from Eq. (5)
128  std::cout << "L_1 - (1/5)[L_3, L_{-2}] = "
129            << (L(1) - (1.0 / 5) * (L(3) * L(-2) - L(-2) * L(3))) << '\n';
130  std::cout << "L_{-1} - (1/3)[L_1, L_{-2}] = "
131            << (L(-1) - (1.0 / 3) * (L(1) * L(-2) - L(-2) * L(1))) << '\n';
132  std::cout << "L_2 - (1/4)[L_3, L_{-1}] = "
133            << (L(2) - (1.0 / 4) * (L(3) * L(-1) - L(-1) * L(3))) << '\n';
134  std::cout << "L_0 - (1/2)[L_1, L_{-1}] = "
135            << (L(0) - (1.0 / 2) * (L(1) * L(-1) - L(-1) * L(1))) << '\n';
136
137  // Check recurrence relation Eq. (6) for some higher positive n
138  for(int n = 3; n < 10; ++n) {
139    std::cout << "L_" << (n + 1) << " - (1/" << (n - 1) << ")"
140              << "[L_" << n << ", L_1] = "
141              << (L(n + 1) - (1.0 / (n - 1)) * (L(n) * L(1) - L(1) * L(n)))
142              << '\n';
143  }
144  // Check recurrence relation Eq. (7) for some higher negative n
145  for(int n = 2; n < 10; ++n) {
146    std::cout << "L_" << (-n - 1) << " - (1/(" << (1 - n) << "))"
147              << "[L_" << -n << ", L_{-1}] = "
148              << (L(-n - 1) - (1.0 / (1 - n)) * (L(-n) * L(-1) - L(-1) * L(-n)))
149              << '\n';
150  }
151
152  return 0;
153}
[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