@@ -24,10 +24,58 @@ Tableau<W> stabilizers_to_tableau(
24
24
25
25
Circuit elimination_instructions;
26
26
27
+ auto fail_due_to_anticommutation = [&]() {
28
+ for (size_t k1 = 0 ; k1 < stabilizers.size (); k1++) {
29
+ for (size_t k2 = k1 + 1 ; k2 < stabilizers.size (); k2++) {
30
+ if (!stabilizers[k1].ref ().commutes (stabilizers[k2])) {
31
+ std::stringstream ss;
32
+ ss << " Some of the given stabilizers anticommute.\n " ;
33
+ ss << " For example:" ;
34
+ ss << " \n stabilizers[" << k1 << " ] = " << stabilizers[k1];
35
+ ss << " \n anticommutes with" ;
36
+ ss << " \n stabilizers[" << k2 << " ] = " << stabilizers[k2];
37
+ throw std::invalid_argument (ss.str ());
38
+ }
39
+ }
40
+ }
41
+ throw std::invalid_argument (
42
+ " The given stabilizers commute but the solver failed in a way that suggests they anticommute. Please "
43
+ " report this as a bug." );
44
+ };
45
+
46
+ auto print_redundant_z_product_parts = [&](size_t stabilizer_index, std::ostream &out) {
47
+ PauliString<W> target = stabilizers[stabilizer_index];
48
+ target.ensure_num_qubits (num_qubits, 1.0 );
49
+ target = target.ref ().after (elimination_instructions);
50
+ if (num_qubits > 0 ) {
51
+ GateTarget t = GateTarget::qubit (num_qubits - 1 );
52
+ elimination_instructions.safe_append (CircuitInstruction{GateType::X, {}, &t});
53
+ elimination_instructions.safe_append (CircuitInstruction{GateType::X, {}, &t});
54
+ }
55
+ Tableau<W> inverse = circuit_to_tableau<W>(elimination_instructions, false , false , false , true );
56
+ target.ref ().for_each_active_pauli ([&](size_t q) {
57
+ out << " \n " ;
58
+ for (size_t k = 0 ; k < stabilizers.size (); k++) {
59
+ PauliString<W> s = stabilizers[k];
60
+ s.ensure_num_qubits (num_qubits, 1.0 );
61
+ if (s == inverse.zs [q]) {
62
+ out << " stabilizers[" << k << " ] = " << stabilizers[k];
63
+ return ;
64
+ }
65
+ }
66
+ out << inverse.zs [q];
67
+ });
68
+ };
69
+
27
70
size_t used = 0 ;
28
71
for (size_t k = 0 ; k < stabilizers.size (); k++) {
29
72
// Find a non-identity term in the Pauli string past the region used by other stabilizers.
30
73
size_t pivot;
74
+ for (size_t q = 0 ; q < used; q++) {
75
+ if (buf_xs[q][k]) {
76
+ fail_due_to_anticommutation ();
77
+ }
78
+ }
31
79
for (pivot = used; pivot < num_qubits; pivot++) {
32
80
if (buf_xs[pivot][k] || buf_zs[pivot][k]) {
33
81
break ;
@@ -37,12 +85,26 @@ Tableau<W> stabilizers_to_tableau(
37
85
// Check for incompatible / redundant stabilizers.
38
86
if (pivot == num_qubits) {
39
87
if (buf_signs[k]) {
40
- throw std::invalid_argument (" Some of the given stabilizers contradict each other." );
88
+ std::stringstream ss;
89
+ ss << " Some of the given stabilizers contradict each other.\n " ;
90
+ ss << " For example:" ;
91
+ ss << " \n stabilizers[" << k << " ] = " << stabilizers[k];
92
+ ss << " \n is the negation of the product of the following stabilizers: {" ;
93
+ print_redundant_z_product_parts (k, ss);
94
+ ss << " \n }" ;
95
+ throw std::invalid_argument (ss.str ());
41
96
}
42
97
if (!allow_redundant) {
43
- throw std::invalid_argument (
44
- " Didn't specify allow_redundant=True but one of the given stabilizers is a product of the others. "
45
- " To allow redundant stabilizers, pass the argument allow_redundant=True." );
98
+ std::stringstream ss;
99
+ ss << " Some of the given stabilizers are redundant." ;
100
+ ss<< " \n To allow redundant stabilizers, pass the argument allow_redundant=True." ;
101
+ ss << " \n " ;
102
+ ss << " \n For example:" ;
103
+ ss << " \n stabilizers[" << k << " ] = " << stabilizers[k];
104
+ ss << " \n is the product of the following stabilizers: {" ;
105
+ print_redundant_z_product_parts (k, ss);
106
+ ss << " \n }" ;
107
+ throw std::invalid_argument (ss.str ());
46
108
}
47
109
continue ;
48
110
}
@@ -140,28 +202,6 @@ Tableau<W> stabilizers_to_tableau(
140
202
used++;
141
203
}
142
204
143
- // All stabilizers will have been mapped into Z products, if they commuted.
144
- for (size_t q = 0 ; q < num_qubits; q++) {
145
- if (buf_xs[q].not_zero ()) {
146
- for (size_t k1 = 0 ; k1 < stabilizers.size (); k1++) {
147
- for (size_t k2 = k1 + 1 ; k2 < stabilizers.size (); k2++) {
148
- if (!stabilizers[k1].ref ().commutes (stabilizers[k2])) {
149
- std::stringstream ss;
150
- ss << " Some of the given stabilizers anticommute.\n " ;
151
- ss << " For example:\n " ;
152
- ss << stabilizers[k1];
153
- ss << " \n anticommutes with\n " ;
154
- ss << stabilizers[k2] << " \n " ;
155
- throw std::invalid_argument (ss.str ());
156
- }
157
- }
158
- }
159
- throw std::invalid_argument (
160
- " The given stabilizers commute but the solver failed in a way that suggests they anticommute. Please "
161
- " report this as a bug." );
162
- }
163
- }
164
-
165
205
if (used < num_qubits) {
166
206
if (!allow_underconstrained) {
167
207
throw std::invalid_argument (
0 commit comments