@@ -149,7 +149,7 @@ std::vector<std::vector<std::complex<float>>> tableau_to_unitary(const Tableau<W
149
149
}
150
150
151
151
template <size_t W>
152
- Tableau<W> circuit_to_tableau (const Circuit &circuit, bool ignore_noise, bool ignore_measurement, bool ignore_reset) {
152
+ Tableau<W> circuit_to_tableau (const Circuit &circuit, bool ignore_noise, bool ignore_measurement, bool ignore_reset, bool inverse ) {
153
153
Tableau<W> result (circuit.count_qubits ());
154
154
TableauSimulator<W> sim (std::mt19937_64 (0 ), circuit.count_qubits ());
155
155
@@ -185,7 +185,10 @@ Tableau<W> circuit_to_tableau(const Circuit &circuit, bool ignore_noise, bool ig
185
185
}
186
186
});
187
187
188
- return sim.inv_state .inverse ();
188
+ if (!inverse) {
189
+ return sim.inv_state .inverse ();
190
+ }
191
+ return sim.inv_state ;
189
192
}
190
193
191
194
template <size_t W>
@@ -556,7 +559,7 @@ Tableau<W> stabilizers_to_tableau(
556
559
}
557
560
558
561
for (size_t k1 = 0 ; k1 < stabilizers.size (); k1++) {
559
- for (size_t k2 = 0 ; k2 < stabilizers.size (); k2++) {
562
+ for (size_t k2 = k1 + 1 ; k2 < stabilizers.size (); k2++) {
560
563
if (!stabilizers[k1].ref ().commutes (stabilizers[k2])) {
561
564
std::stringstream ss;
562
565
ss << " Some of the given stabilizers anticommute.\n " ;
@@ -568,44 +571,39 @@ Tableau<W> stabilizers_to_tableau(
568
571
}
569
572
}
570
573
}
571
- Tableau<W> inverted (num_qubits);
572
-
573
- PauliString<W> cur (num_qubits);
574
- std::vector<size_t > targets;
575
- while (targets.size () < num_qubits) {
576
- targets.push_back (targets.size ());
577
- }
578
- auto overwrite_cur_apply_recorded = [&](const PauliString<W> &e) {
579
- PauliStringRef<W> cur_ref = cur.ref ();
580
- cur.xs .clear ();
581
- cur.zs .clear ();
582
- cur.xs .word_range_ref (0 , e.xs .num_simd_words ) = e.xs ;
583
- cur.zs .word_range_ref (0 , e.xs .num_simd_words ) = e.zs ;
584
- cur.sign = e.sign ;
585
- inverted.apply_within (cur_ref, targets);
586
- };
574
+ Circuit elimination_instructions;
575
+ PauliString<W> buf (num_qubits);
587
576
588
577
size_t used = 0 ;
589
578
for (const auto &e : stabilizers) {
590
- overwrite_cur_apply_recorded (e);
579
+ if (e.num_qubits == num_qubits) {
580
+ buf = e;
581
+ } else {
582
+ buf.xs .clear ();
583
+ buf.zs .clear ();
584
+ memcpy (buf.xs .u8 , e.xs .u8 , e.xs .num_u8_padded ());
585
+ memcpy (buf.zs .u8 , e.zs .u8 , e.zs .num_u8_padded ());
586
+ buf.sign = e.sign ;
587
+ }
588
+ buf.ref ().do_circuit (elimination_instructions);
591
589
592
590
// Find a non-identity term in the Pauli string past the region used by other stabilizers.
593
591
size_t pivot;
594
592
for (pivot = used; pivot < num_qubits; pivot++) {
595
- if (cur .xs [pivot] || cur .zs [pivot]) {
593
+ if (buf .xs [pivot] || buf .zs [pivot]) {
596
594
break ;
597
595
}
598
596
}
599
597
600
598
// Check for incompatible / redundant stabilizers.
601
599
if (pivot == num_qubits) {
602
- if (cur .xs .not_zero ()) {
600
+ if (buf .xs .not_zero ()) {
603
601
throw std::invalid_argument (" Some of the given stabilizers anticommute." );
604
602
}
605
- if (cur .sign ) {
603
+ if (buf .sign ) {
606
604
throw std::invalid_argument (" Some of the given stabilizers contradict each other." );
607
605
}
608
- if (!allow_redundant && cur .zs .not_zero ()) {
606
+ if (!allow_redundant && buf .zs .not_zero ()) {
609
607
throw std::invalid_argument (
610
608
" Didn't specify allow_redundant=True but one of the given stabilizers is a product of the others. "
611
609
" To allow redundant stabilizers, pass the argument allow_redundant=True." );
@@ -614,32 +612,36 @@ Tableau<W> stabilizers_to_tableau(
614
612
}
615
613
616
614
// Change pivot basis to the Z axis.
617
- if (cur.xs [pivot]) {
618
- std::string name = cur.zs [pivot] ? " H_YZ" : " H_XZ" ;
619
- inverted.inplace_scatter_append (GATE_DATA.at (name).tableau <W>(), {pivot});
615
+ if (buf.xs [pivot]) {
616
+ GateType g = buf.zs [pivot] ? GateType::H_YZ : GateType::H;
617
+ GateTarget t = GateTarget::qubit (pivot);
618
+ CircuitInstruction instruction{g, {}, &t};
619
+ elimination_instructions.safe_append (instruction);
620
+ buf.ref ().do_instruction (instruction);
620
621
}
621
622
// Cancel other terms in Pauli string.
622
623
for (size_t q = 0 ; q < num_qubits; q++) {
623
- int p = cur .xs [q] + cur .zs [q] * 2 ;
624
+ int p = buf .xs [q] + buf .zs [q] * 2 ;
624
625
if (p && q != pivot) {
625
- inverted.inplace_scatter_append (
626
- GATE_DATA.at (p == 1 ? " XCX"
627
- : p == 2 ? " XCZ"
628
- : " XCY" )
629
- .tableau <W>(),
630
- {pivot, q});
626
+ std::array<GateTarget, 2 > targets{GateTarget::qubit (pivot), GateTarget::qubit (q)};
627
+ CircuitInstruction instruction{p == 1 ? GateType::XCX : p == 2 ? GateType::XCZ : GateType::XCY, {}, targets};
628
+ elimination_instructions.safe_append (instruction);
629
+ buf.ref ().do_instruction (instruction);
631
630
}
632
631
}
633
632
634
633
// Move pivot to diagonal.
635
634
if (pivot != used) {
636
- inverted.inplace_scatter_append (GATE_DATA.at (" SWAP" ).tableau <W>(), {pivot, used});
635
+ std::array<GateTarget, 2 > targets{GateTarget::qubit (pivot), GateTarget::qubit (used)};
636
+ CircuitInstruction instruction{GateType::SWAP, {}, targets};
637
+ elimination_instructions.safe_append (instruction);
637
638
}
638
639
639
640
// Fix sign.
640
- overwrite_cur_apply_recorded (e);
641
- if (cur.sign ) {
642
- inverted.inplace_scatter_append (GATE_DATA.at (" X" ).tableau <W>(), {used});
641
+ if (buf.sign ) {
642
+ GateTarget t = GateTarget::qubit (used);
643
+ CircuitInstruction instruction{GateType::X, {}, &t};
644
+ elimination_instructions.safe_append (instruction);
643
645
}
644
646
645
647
used++;
@@ -653,10 +655,17 @@ Tableau<W> stabilizers_to_tableau(
653
655
}
654
656
}
655
657
658
+ if (num_qubits > 0 ) {
659
+ // Force size of resulting tableau to be correct.
660
+ GateTarget t = GateTarget::qubit (num_qubits - 1 );
661
+ elimination_instructions.safe_append (CircuitInstruction{GateType::X, {}, &t});
662
+ elimination_instructions.safe_append (CircuitInstruction{GateType::X, {}, &t});
663
+ }
664
+
656
665
if (invert) {
657
- return inverted ;
666
+ return circuit_to_tableau<W>(elimination_instructions. inverse (), false , false , false , true ) ;
658
667
}
659
- return inverted. inverse ( );
668
+ return circuit_to_tableau<W>(elimination_instructions, false , false , false , true );
660
669
}
661
670
662
671
} // namespace stim
0 commit comments