Skip to content

Commit

Permalink
Add CZSWAP, add specialized pauli string ops
Browse files Browse the repository at this point in the history
  • Loading branch information
Strilanc committed Jan 24, 2024
1 parent 79b058e commit 242019a
Show file tree
Hide file tree
Showing 26 changed files with 1,181 additions and 119 deletions.
1 change: 1 addition & 0 deletions file_lists/test_files
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ src/stim/stabilizers/conversions.test.cc
src/stim/stabilizers/flex_pauli_string.test.cc
src/stim/stabilizers/pauli_string.test.cc
src/stim/stabilizers/pauli_string_iter.test.cc
src/stim/stabilizers/pauli_string_ref.test.cc
src/stim/stabilizers/tableau.test.cc
src/stim/stabilizers/tableau_iter.test.cc
src/stim/str_util.test.cc
Expand Down
1 change: 1 addition & 0 deletions src/stim/circuit/circuit.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,7 @@ Circuit stim::generate_test_circuit_with_all_operations() {
ISWAP_DAG 4 5
SWAP 6 7
SWAPCX 8 9
CZSWAP 10 11
SQRT_XX 0 1
SQRT_XX_DAG 2 3
SQRT_YY 4 5
Expand Down
7 changes: 4 additions & 3 deletions src/stim/circuit/export_qasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ struct QasmExporter {
target = t1;
break;
default:
throw std::invalid_argument("Not implemented: " + instruction.str());
throw std::invalid_argument("Not implemented in output_two_qubit_unitary_instruction_with_possible_feedback: " + instruction.str());
}

out << "if (";
Expand All @@ -279,7 +279,7 @@ struct QasmExporter {
}
out << "sweep[" << control.value() << "]";
} else {
throw std::invalid_argument("Not implemented: " + instruction.str());
throw std::invalid_argument("Not implemented in output_two_qubit_unitary_instruction_with_possible_feedback: " + instruction.str());
}
out << ") {\n";
out << " " << basis << " q[" << target.qubit_value() << "];\n";
Expand Down Expand Up @@ -415,6 +415,7 @@ struct QasmExporter {
define_custom_single_qubit_gate(GateType::SQRT_Y_DAG, "sydg");

define_custom_decomposed_gate(GateType::CXSWAP, "cxswap");
define_custom_decomposed_gate(GateType::CZSWAP, "czswap");
define_custom_decomposed_gate(GateType::ISWAP, "iswap");
define_custom_decomposed_gate(GateType::ISWAP_DAG, "iswapdg");
define_custom_decomposed_gate(GateType::SQRT_XX, "sxx");
Expand Down Expand Up @@ -557,7 +558,7 @@ struct QasmExporter {
}
}

throw std::invalid_argument("Not implemented: " + instruction.str());
throw std::invalid_argument("Not implemented in QasmExporter::output_instruction: " + instruction.str());
}
};

Expand Down
4 changes: 4 additions & 0 deletions src/stim/circuit/export_qasm.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ gate hyz q0 { U(pi/2, pi/2, pi/2) q0; }
gate sy q0 { U(pi/2, 0, 0) q0; }
gate sydg q0 { U(pi/2, pi/2, pi/2) q0; }
gate cxswap q0, q1 { cx q1, q0; cx q0, q1; }
gate czswap q0, q1 { h q0; cx q0, q1; cx q1, q0; h q1; }
gate iswap q0, q1 { h q0; cx q0, q1; cx q1, q0; h q1; s q1; s q0; }
gate iswapdg q0, q1 { s q0; s q0; s q0; s q1; s q1; s q1; h q1; cx q1, q0; cx q0, q1; h q0; }
gate sxx q0, q1 { h q0; cx q0, q1; h q1; s q0; s q1; h q0; h q1; }
Expand Down Expand Up @@ -317,6 +318,7 @@ iswap q[2], q[3];
iswapdg q[4], q[5];
swap q[6], q[7];
swapcx q[8], q[9];
czswap q[10], q[11];
sxx q[0], q[1];
sxxdg q[2], q[3];
syy q[4], q[5];
Expand Down Expand Up @@ -419,6 +421,7 @@ gate hyz q0 { U(pi/2, pi/2, pi/2) q0; }
gate sy q0 { U(pi/2, 0, 0) q0; }
gate sydg q0 { U(pi/2, pi/2, pi/2) q0; }
gate cxswap q0, q1 { cx q1, q0; cx q0, q1; }
gate czswap q0, q1 { h q0; cx q0, q1; cx q1, q0; h q1; }
gate iswap q0, q1 { h q0; cx q0, q1; cx q1, q0; h q1; s q1; s q0; }
gate iswapdg q0, q1 { s q0; s q0; s q0; s q1; s q1; s q1; h q1; cx q1, q0; cx q0, q1; h q0; }
gate sxx q0, q1 { h q0; cx q0, q1; h q1; s q0; s q1; h q0; h q1; }
Expand Down Expand Up @@ -462,6 +465,7 @@ iswap q[2], q[3];
iswapdg q[4], q[5];
swap q[6], q[7];
swapcx q[8], q[9];
czswap q[10], q[11];
sxx q[0], q[1];
sxxdg q[2], q[3];
syy q[4], q[5];
Expand Down
2 changes: 2 additions & 0 deletions src/stim/diagram/diagram_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ std::pair<std::string, std::string> stim_draw_internal::two_qubit_gate_pieces(Ga
return {"Y", "Z"};
} else if (gate_type == GateType::CXSWAP) {
return {"ZSWAP", "XSWAP"};
} else if (gate_type == GateType::CZSWAP) {
return {"ZSWAP", "ZSWAP"};
} else if (gate_type == GateType::SWAPCX) {
return {"XSWAP", "ZSWAP"};
} else {
Expand Down
6 changes: 3 additions & 3 deletions src/stim/diagram/timeline/timeline_ascii_drawer.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,9 @@ TEST(circuit_diagram_timeline_text, test_circuit_all_ops) {
| | | | |
q9: ----------------------------------------ZSWAP-----SQRT_ZZ-----Y-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------R----------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------
| |
q10: --------------------------------------------------SQRT_ZZ_DAG-Y------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------
| | | |
q11: --------------------------------------------------SQRT_ZZ_DAG-@------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------
q10: ----------------------------------------ZSWAP-----SQRT_ZZ_DAG-Y------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------
| | | | |
q11: ----------------------------------------ZSWAP-----SQRT_ZZ_DAG-@------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------
| |
q12: --------------------------------------------------------------@------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|----------------------------------------------------------------------------------------------------------------------------------------------------------
| | |
Expand Down
32 changes: 32 additions & 0 deletions src/stim/gates/gate_data_swaps.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,36 @@ CNOT 0 1
CNOT 1 0
)CIRCUIT",
});

add_gate(
failed,
Gate{
.name = "CZSWAP",
.id = GateType::CZSWAP,
.best_candidate_inverse_id = GateType::CZSWAP,
.arg_count = 0,
.flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS),
.category = "C_Two Qubit Clifford Gates",
.help = R"MARKDOWN(
A combination CZ-and-SWAP gate.
This gate is kak-equivalent to the iswap gate.
Parens Arguments:
This instruction takes no parens arguments.
Targets:
Qubit pairs to operate on.
)MARKDOWN",
.unitary_data = {{1, 0, 0, 0}, {0, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, -1}},
.flow_data = {"+ZX", "+IZ", "+XZ", "+ZI"},
.h_s_cx_m_r_decomposition = R"CIRCUIT(
H 0
CX 0 1
CX 1 0
H 1
)CIRCUIT",
});
add_gate_alias(failed, "SWAPCZ", "CZSWAP");
}
3 changes: 2 additions & 1 deletion src/stim/gates/gates.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ constexpr inline uint16_t gate_name_to_hash(const char *c) {
return gate_name_to_hash(c, std::char_traits<char>::length(c));
}

constexpr const size_t NUM_DEFINED_GATES = 67;
constexpr const size_t NUM_DEFINED_GATES = 68;

enum class GateType : uint8_t {
NOT_A_GATE = 0,
Expand Down Expand Up @@ -154,6 +154,7 @@ enum class GateType : uint8_t {
ISWAP,
CXSWAP,
SWAPCX,
CZSWAP,
ISWAP_DAG,
// Pair measurement gates
MXX,
Expand Down
6 changes: 6 additions & 0 deletions src/stim/simulators/error_analyzer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,9 @@ void ErrorAnalyzer::undo_gate(const CircuitInstruction &inst) {
case GateType::CXSWAP:
undo_CXSWAP(inst);
break;
case GateType::CZSWAP:
undo_CZSWAP(inst);
break;
case GateType::SWAPCX:
undo_SWAPCX(inst);
break;
Expand Down Expand Up @@ -609,6 +612,9 @@ void ErrorAnalyzer::undo_ISWAP(const CircuitInstruction &dat) {
void ErrorAnalyzer::undo_CXSWAP(const CircuitInstruction &dat) {
tracker.undo_CXSWAP(dat);
}
void ErrorAnalyzer::undo_CZSWAP(const CircuitInstruction &dat) {
tracker.undo_CZSWAP(dat);
}
void ErrorAnalyzer::undo_SWAPCX(const CircuitInstruction &dat) {
tracker.undo_SWAPCX(dat);
}
Expand Down
1 change: 1 addition & 0 deletions src/stim/simulators/error_analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ struct ErrorAnalyzer {
void undo_PAULI_CHANNEL_2(const CircuitInstruction &inst);
void undo_ISWAP(const CircuitInstruction &inst);
void undo_CXSWAP(const CircuitInstruction &inst);
void undo_CZSWAP(const CircuitInstruction &inst);
void undo_SWAPCX(const CircuitInstruction &inst);

void undo_RX_with_context(const CircuitInstruction &inst, const char *context_op);
Expand Down
2 changes: 1 addition & 1 deletion src/stim/simulators/error_matcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ void ErrorMatcher::rev_process_instruction(const CircuitInstruction &op) {
} else if (op.gate_type == GateType::M || op.gate_type == GateType::MR) {
err_m(op, TARGET_PAULI_Z_BIT);
} else {
throw std::invalid_argument("Not implemented: " + std::string(GATE_DATA[op.gate_type].name));
throw std::invalid_argument("Not implemented in ErrorMatcher::rev_process_instruction: " + std::string(GATE_DATA[op.gate_type].name));
}
}

Expand Down
1 change: 1 addition & 0 deletions src/stim/simulators/frame_simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ struct FrameSimulator {
void do_SWAP(const CircuitInstruction &inst);
void do_ISWAP(const CircuitInstruction &inst);
void do_CXSWAP(const CircuitInstruction &inst);
void do_CZSWAP(const CircuitInstruction &inst);
void do_SWAPCX(const CircuitInstruction &inst);
void do_MPP(const CircuitInstruction &inst);
void do_MXX(const CircuitInstruction &inst);
Expand Down
16 changes: 15 additions & 1 deletion src/stim/simulators/frame_simulator.inl
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,17 @@ void FrameSimulator<W>::do_CXSWAP(const CircuitInstruction &target_data) {
});
}

template <size_t W>
void FrameSimulator<W>::do_CZSWAP(const CircuitInstruction &target_data) {
for_each_target_pair(
*this, target_data, [](simd_word<W> &x1, simd_word<W> &z1, simd_word<W> &x2, simd_word<W> &z2) {
std::swap(z1, z2);
std::swap(x1, x2);
z1 ^= x2;
z2 ^= x1;
});
}

template <size_t W>
void FrameSimulator<W>::do_SWAPCX(const CircuitInstruction &target_data) {
for_each_target_pair(
Expand Down Expand Up @@ -1006,6 +1017,9 @@ void FrameSimulator<W>::do_gate(const CircuitInstruction &inst) {
case GateType::CXSWAP:
do_CXSWAP(inst);
break;
case GateType::CZSWAP:
do_CZSWAP(inst);
break;
case GateType::SWAPCX:
do_SWAPCX(inst);
break;
Expand Down Expand Up @@ -1065,7 +1079,7 @@ void FrameSimulator<W>::do_gate(const CircuitInstruction &inst) {
break;

default:
throw std::invalid_argument("Not implemented: " + inst.str());
throw std::invalid_argument("Not implemented in FrameSimulator<W>::do_gate: " + inst.str());
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/stim/simulators/graph_simulator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ GraphSimulator::GraphSimulator(size_t num_qubits)

void GraphSimulator::do_1q_gate(GateType gate, size_t qubit) {
GateTarget t = GateTarget::qubit(qubit);
x2outs.ref().after_inplace(CircuitInstruction{gate, {}, &t}, false);
z2outs.ref().after_inplace(CircuitInstruction{gate, {}, &t}, false);
x2outs.ref().do_instruction(CircuitInstruction{gate, {}, &t});
z2outs.ref().do_instruction(CircuitInstruction{gate, {}, &t});
paulis.xs[qubit] ^= z2outs.sign;
paulis.zs[qubit] ^= x2outs.sign;
x2outs.sign = 0;
Expand Down
14 changes: 14 additions & 0 deletions src/stim/simulators/sparse_rev_frame_tracker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ void SparseUnsignedRevFrameTracker::undo_gate(const CircuitInstruction &inst) {
case GateType::CXSWAP:
undo_CXSWAP(inst);
break;
case GateType::CZSWAP:
undo_CZSWAP(inst);
break;
case GateType::SWAPCX:
undo_SWAPCX(inst);
break;
Expand Down Expand Up @@ -729,6 +732,17 @@ void SparseUnsignedRevFrameTracker::undo_CXSWAP(const CircuitInstruction &dat) {
}
}

void SparseUnsignedRevFrameTracker::undo_CZSWAP(const CircuitInstruction &dat) {
for (size_t k = dat.targets.size() - 2; k + 2 != 0; k -= 2) {
auto a = dat.targets[k].data;
auto b = dat.targets[k + 1].data;
zs[a] ^= xs[b];
zs[b] ^= xs[a];
std::swap(xs[a], xs[b]);
std::swap(zs[a], zs[b]);
}
}

void SparseUnsignedRevFrameTracker::undo_SWAPCX(const CircuitInstruction &dat) {
for (size_t k = dat.targets.size() - 2; k + 2 != 0; k -= 2) {
auto a = dat.targets[k].data;
Expand Down
1 change: 1 addition & 0 deletions src/stim/simulators/sparse_rev_frame_tracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ struct SparseUnsignedRevFrameTracker {
void undo_SWAP(const CircuitInstruction &inst);
void undo_ISWAP(const CircuitInstruction &inst);
void undo_CXSWAP(const CircuitInstruction &inst);
void undo_CZSWAP(const CircuitInstruction &inst);
void undo_SWAPCX(const CircuitInstruction &inst);

template <size_t W>
Expand Down
1 change: 1 addition & 0 deletions src/stim/simulators/tableau_simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct TableauSimulator {
void do_ISWAP(const CircuitInstruction &inst);
void do_ISWAP_DAG(const CircuitInstruction &inst);
void do_CXSWAP(const CircuitInstruction &inst);
void do_CZSWAP(const CircuitInstruction &inst);
void do_SWAPCX(const CircuitInstruction &inst);
void do_XCX(const CircuitInstruction &inst);
void do_XCY(const CircuitInstruction &inst);
Expand Down
15 changes: 15 additions & 0 deletions src/stim/simulators/tableau_simulator.inl
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,18 @@ void TableauSimulator<W>::do_CXSWAP(const CircuitInstruction &target_data) {
}
}

template <size_t W>
void TableauSimulator<W>::do_CZSWAP(const CircuitInstruction &target_data) {
const auto &targets = target_data.targets;
assert(!(targets.size() & 1));
for (size_t k = 0; k < targets.size(); k += 2) {
auto q1 = targets[k].data;
auto q2 = targets[k + 1].data;
inv_state.prepend_ZCZ(q1, q2);
inv_state.prepend_SWAP(q2, q1);
}
}

template <size_t W>
void TableauSimulator<W>::do_SWAPCX(const CircuitInstruction &target_data) {
const auto &targets = target_data.targets;
Expand Down Expand Up @@ -1673,6 +1685,9 @@ void TableauSimulator<W>::do_gate(const CircuitInstruction &inst) {
case GateType::CXSWAP:
do_CXSWAP(inst);
break;
case GateType::CZSWAP:
do_CZSWAP(inst);
break;
case GateType::SWAPCX:
do_SWAPCX(inst);
break;
Expand Down
10 changes: 5 additions & 5 deletions src/stim/stabilizers/pauli_string.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -522,8 +522,8 @@ TEST_EACH_WORD_SIZE_W(pauli_string, before_after_circuit_understands_commutation
MPP X2*Y3*Z4 X5*X6
H 1
)CIRCUIT");
auto before = PauliString<W>::from_str("+_X");
auto after = PauliString<W>::from_str("+_Z");
auto before = PauliString<W>::from_str("+_X_____");
auto after = PauliString<W>::from_str("+_Z_____");
ASSERT_EQ(before.ref().after(c), after);
ASSERT_EQ(after.ref().before(c), before);

Expand All @@ -532,12 +532,12 @@ TEST_EACH_WORD_SIZE_W(pauli_string, before_after_circuit_understands_commutation
ASSERT_EQ(before.ref().after(c), after);
ASSERT_EQ(after.ref().before(c), before);

before = PauliString<W>::from_str("+_XX___");
after = PauliString<W>::from_str("+_ZX___");
before = PauliString<W>::from_str("+_XX____");
after = PauliString<W>::from_str("+_ZX____");
ASSERT_EQ(before.ref().after(c), after);
ASSERT_EQ(after.ref().before(c), before);

before = after = PauliString<W>::from_str("+__ZX");
before = after = PauliString<W>::from_str("+__ZX___");
ASSERT_EQ(before.ref().after(c), after);
ASSERT_EQ(after.ref().before(c), before);

Expand Down
Loading

0 comments on commit 242019a

Please sign in to comment.