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
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,
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}
“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