Skip to content

Commit

Permalink
Update circuit data references plus some house cleaning (#850)
Browse files Browse the repository at this point in the history
- Rerun the getting started notebook with v1.14
- Run autoformatter over the code
  • Loading branch information
Strilanc authored Nov 2, 2024
1 parent 2581b90 commit e6fd563
Show file tree
Hide file tree
Showing 52 changed files with 2,541 additions and 2,219 deletions.
2 changes: 2 additions & 0 deletions doc/circuit_data_references.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@
- [arXiv:2407.13826 ](https://arxiv.org/abs/2407.13826)[Stim circuits for 'Designing fault-tolerant circuits using detector error models'](https://github.com/peter-janderks/short_measurement_schedules_simulations/tree/main/stim_circuits)
- [arXiv:2408.00758](https://arxiv.org/abs/2408.00758)[Stim circuits for ``To reset, or not to reset -- that is the question" manuscript](https://zenodo.org/records/13152440)
- [arXiv:2408.11894](https://arxiv.org/abs/2408.11894)[Stim circuits for 'Automated Synthesis of Fault-Tolerant State Preparation Circuits for Quantum Error Correction Codes'](https://github.com/cda-tum/mqt-qecc/tree/main/src/mqt/qecc/ft_stateprep/eval/circuits)
- [arXiv:2408.13687](https://arxiv.org/abs/2408.13687)[Data for "Quantum error correction below the surface code threshold"](https://zenodo.org/records/13273331)
- [arXiv:2409.17595](https://arxiv.org/abs/2409.17595)[Data for "Magic state cultivation: growing T states as cheap as CNOT gates"](https://zenodo.org/records/13777072)
1,612 changes: 851 additions & 761 deletions doc/getting_started.ipynb

Large diffs are not rendered by default.

15 changes: 9 additions & 6 deletions src/stim/circuit/circuit.cc
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ void circuit_read_single_operation(Circuit &circuit, char lead_char, SOURCE read
}

circuit.tag_buf.commit_tail();
circuit.operations.push_back(CircuitInstruction(gate.id, circuit.arg_buf.commit_tail(), circuit.target_buf.commit_tail(), tail_tag));
circuit.operations.push_back(
CircuitInstruction(gate.id, circuit.arg_buf.commit_tail(), circuit.target_buf.commit_tail(), tail_tag));
}

void Circuit::try_fuse_last_two_ops() {
Expand Down Expand Up @@ -411,7 +412,8 @@ void Circuit::safe_insert(size_t index, const Circuit &circuit) {
}
}

void Circuit::safe_insert_repeat_block(size_t index, uint64_t repeat_count, const Circuit &block, std::string_view tag) {
void Circuit::safe_insert_repeat_block(
size_t index, uint64_t repeat_count, const Circuit &block, std::string_view tag) {
if (repeat_count == 0) {
throw std::invalid_argument("Can't repeat 0 times.");
}
Expand All @@ -426,8 +428,7 @@ void Circuit::safe_insert_repeat_block(size_t index, uint64_t repeat_count, cons
operations.insert(operations.begin() + index, CircuitInstruction(GateType::REPEAT, {}, targets, tag));
}

void Circuit::safe_append_reversed_targets(
CircuitInstruction instruction, bool reverse_in_pairs) {
void Circuit::safe_append_reversed_targets(CircuitInstruction instruction, bool reverse_in_pairs) {
if (reverse_in_pairs) {
if (instruction.targets.size() % 2 != 0) {
throw std::invalid_argument("targets.size() % 2 != 0");
Expand Down Expand Up @@ -779,7 +780,8 @@ const Circuit Circuit::aliased_noiseless_circuit() const {
auto &tail = result.target_buf.tail;
tail.ptr_end = tail.ptr_start + op.targets.size();
memset(tail.ptr_start, 0, (tail.ptr_end - tail.ptr_start) * sizeof(GateTarget));
result.operations.push_back(CircuitInstruction(GateType::MPAD, {}, result.target_buf.commit_tail(), op.tag));
result.operations.push_back(
CircuitInstruction(GateType::MPAD, {}, result.target_buf.commit_tail(), op.tag));
result.try_fuse_last_two_ops();
} else {
// Drop result flip probability.
Expand Down Expand Up @@ -812,7 +814,8 @@ Circuit Circuit::without_noise() const {
tail.ptr_end = tail.ptr_start + op.targets.size();
memset(tail.ptr_start, 0, (tail.ptr_end - tail.ptr_start) * sizeof(GateTarget));
auto tag = result.tag_buf.take_copy(op.tag);
result.operations.push_back(CircuitInstruction(GateType::MPAD, {}, result.target_buf.commit_tail(), tag));
result.operations.push_back(
CircuitInstruction(GateType::MPAD, {}, result.target_buf.commit_tail(), tag));
} else {
// Drop result flip probabilities.
auto targets = result.target_buf.take_copy(op.targets);
Expand Down
3 changes: 1 addition & 2 deletions src/stim/circuit/circuit.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ struct Circuit {
void safe_insert(size_t index, const Circuit &circuit);

/// Appends the given gate, but with targets reversed.
void safe_append_reversed_targets(
CircuitInstruction instruction, bool reverse_in_pairs);
void safe_append_reversed_targets(CircuitInstruction instruction, bool reverse_in_pairs);

/// Resets the circuit back to an empty circuit.
void clear();
Expand Down
31 changes: 17 additions & 14 deletions src/stim/circuit/circuit.pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ pybind11::object circuit_get_item(const Circuit &self, const pybind11::object &i

auto &op = self.operations[index];
if (op.gate_type == GateType::REPEAT) {
return pybind11::cast(CircuitRepeatBlock{op.repeat_block_rep_count(), op.repeat_block_body(self), pybind11::str(op.tag)});
return pybind11::cast(
CircuitRepeatBlock{op.repeat_block_rep_count(), op.repeat_block_body(self), pybind11::str(op.tag)});
}
std::vector<GateTarget> targets;
for (const auto &e : op.targets) {
Expand Down Expand Up @@ -292,12 +293,13 @@ void circuit_append(
}

const PyCircuitInstruction &instruction = pybind11::cast<PyCircuitInstruction>(obj);
self.safe_append(CircuitInstruction{
instruction.gate_type,
instruction.gate_args,
instruction.targets,
pybind11::cast<std::string_view>(instruction.tag),
});
self.safe_append(
CircuitInstruction{
instruction.gate_type,
instruction.gate_args,
instruction.targets,
pybind11::cast<std::string_view>(instruction.tag),
});
} else if (pybind11::isinstance<CircuitRepeatBlock>(obj)) {
if (!raw_targets.empty() || !arg.is_none()) {
throw std::invalid_argument("Can't specify `targets` or `arg` when appending a stim.CircuitRepeatBlock.");
Expand Down Expand Up @@ -2040,13 +2042,14 @@ void stim_pybind::pybind_circuit_methods(pybind11::module &, pybind11::class_<Ci
)DOC")
.data());

c.def(pybind11::pickle(
[](const Circuit &self) -> pybind11::str {
return self.str();
},
[](const pybind11::str &text) {
return Circuit(pybind11::cast<std::string_view>(text));
}));
c.def(
pybind11::pickle(
[](const Circuit &self) -> pybind11::str {
return self.str();
},
[](const pybind11::str &text) {
return Circuit(pybind11::cast<std::string_view>(text));
}));

c.def(
"shortest_graphlike_error",
Expand Down
3 changes: 2 additions & 1 deletion src/stim/circuit/circuit_instruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ bool CircuitInstruction::operator==(const CircuitInstruction &other) const {
return gate_type == other.gate_type && args == other.args && targets == other.targets && tag == other.tag;
}
bool CircuitInstruction::approx_equals(const CircuitInstruction &other, double atol) const {
if (gate_type != other.gate_type || targets != other.targets || args.size() != other.args.size() || tag != other.tag) {
if (gate_type != other.gate_type || targets != other.targets || args.size() != other.args.size() ||
tag != other.tag) {
return false;
}
for (size_t k = 0; k < args.size(); k++) {
Expand Down
7 changes: 5 additions & 2 deletions src/stim/circuit/circuit_instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ struct CircuitInstruction {
std::string_view tag;

CircuitInstruction() = delete;
CircuitInstruction(GateType gate_type, SpanRef<const double> args, SpanRef<const GateTarget> targets, std::string_view tag);
CircuitInstruction(
GateType gate_type, SpanRef<const double> args, SpanRef<const GateTarget> targets, std::string_view tag);

/// Computes number of qubits, number of measurements, etc.
CircuitStats compute_stats(const Circuit *host) const;
Expand Down Expand Up @@ -129,7 +130,9 @@ struct CircuitInstruction {
end = start + 1;
} else if (flags & stim::GateFlags::GATE_TARGETS_PAIRS) {
end = start + 2;
} else if ((flags & stim::GateFlags::GATE_TARGETS_PAULI_STRING) && !(flags & stim::GateFlags::GATE_TARGETS_COMBINERS)) {
} else if (
(flags & stim::GateFlags::GATE_TARGETS_PAULI_STRING) &&
!(flags & stim::GateFlags::GATE_TARGETS_COMBINERS)) {
// like CORRELATED_ERROR
end = targets.size();
} else if (flags & stim::GateFlags::GATE_ONLY_TARGETS_MEASUREMENT_RECORD) {
Expand Down
45 changes: 23 additions & 22 deletions src/stim/circuit/circuit_instruction.pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ using namespace stim;
using namespace stim_pybind;

PyCircuitInstruction::PyCircuitInstruction(
std::string_view name, std::span<pybind11::object> init_targets, std::span<double> init_gate_args, pybind11::str tag)
std::string_view name,
std::span<pybind11::object> init_targets,
std::span<double> init_gate_args,
pybind11::str tag)
: gate_type(GATE_DATA.at(name).id), tag(tag) {
for (const auto &obj : init_gate_args) {
gate_args.push_back(obj);
Expand Down Expand Up @@ -49,7 +52,8 @@ PyCircuitInstruction PyCircuitInstruction::from_instruction(CircuitInstruction i
}

bool PyCircuitInstruction::operator==(const PyCircuitInstruction &other) const {
return gate_type == other.gate_type && targets == other.targets && gate_args == other.gate_args && pybind11::cast<std::string_view>(tag) == pybind11::cast<std::string_view>(other.tag);
return gate_type == other.gate_type && targets == other.targets && gate_args == other.gate_args &&
pybind11::cast<std::string_view>(tag) == pybind11::cast<std::string_view>(other.tag);
}
bool PyCircuitInstruction::operator!=(const PyCircuitInstruction &other) const {
return !(*this == other);
Expand Down Expand Up @@ -83,12 +87,7 @@ std::string PyCircuitInstruction::str() const {
}

CircuitInstruction PyCircuitInstruction::as_operation_ref() const {
return CircuitInstruction{
gate_type,
gate_args,
targets,
pybind11::cast<std::string_view>(tag)
};
return CircuitInstruction{gate_type, gate_args, targets, pybind11::cast<std::string_view>(tag)};
}
PyCircuitInstruction::operator CircuitInstruction() const {
return as_operation_ref();
Expand Down Expand Up @@ -149,20 +148,22 @@ pybind11::class_<PyCircuitInstruction> stim_pybind::pybind_circuit_instruction(p
}
void stim_pybind::pybind_circuit_instruction_methods(pybind11::module &m, pybind11::class_<PyCircuitInstruction> &c) {
c.def(
pybind11::init([](std::string_view name, pybind11::object targets, pybind11::object gate_args, pybind11::str tag) -> PyCircuitInstruction {
if (targets.is_none() and gate_args.is_none() && !pybind11::cast<bool>(pybind11::bool_(tag))) {
return PyCircuitInstruction::from_str(name);
}
std::vector<double> conv_args;
std::vector<pybind11::object> conv_targets;
if (!gate_args.is_none()) {
conv_args = pybind11::cast<std::vector<double>>(gate_args);
}
if (!targets.is_none()) {
conv_targets = pybind11::cast<std::vector<pybind11::object>>(targets);
}
return PyCircuitInstruction(name, conv_targets, conv_args, tag);
}),
pybind11::init(
[](std::string_view name, pybind11::object targets, pybind11::object gate_args, pybind11::str tag)
-> PyCircuitInstruction {
if (targets.is_none() and gate_args.is_none() && !pybind11::cast<bool>(pybind11::bool_(tag))) {
return PyCircuitInstruction::from_str(name);
}
std::vector<double> conv_args;
std::vector<pybind11::object> conv_targets;
if (!gate_args.is_none()) {
conv_args = pybind11::cast<std::vector<double>>(gate_args);
}
if (!targets.is_none()) {
conv_targets = pybind11::cast<std::vector<pybind11::object>>(targets);
}
return PyCircuitInstruction(name, conv_targets, conv_args, tag);
}),
pybind11::arg("name"),
pybind11::arg("targets") = pybind11::none(),
pybind11::arg("gate_args") = pybind11::none(),
Expand Down
5 changes: 4 additions & 1 deletion src/stim/circuit/circuit_instruction.pybind.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ struct PyCircuitInstruction {
PyCircuitInstruction(
std::string_view name, std::span<pybind11::object> targets, std::span<double> gate_args, pybind11::str tag);
PyCircuitInstruction(
stim::GateType gate_type, std::vector<stim::GateTarget> targets, std::vector<double> gate_args, pybind11::str tag);
stim::GateType gate_type,
std::vector<stim::GateTarget> targets,
std::vector<double> gate_args,
pybind11::str tag);
static PyCircuitInstruction from_str(std::string_view text);
static PyCircuitInstruction from_instruction(stim::CircuitInstruction instruction);

Expand Down
68 changes: 38 additions & 30 deletions src/stim/circuit/circuit_instruction.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,36 +31,44 @@ TEST(circuit_instruction, for_combined_targets) {
});
return results;
};
ASSERT_EQ(get_k(0), (std::vector<std::vector<GateTarget>>{
}));
ASSERT_EQ(get_k(1), (std::vector<std::vector<GateTarget>>{
}));
ASSERT_EQ(get_k(2), (std::vector<std::vector<GateTarget>>{
{GateTarget::qubit(1)},
}));
ASSERT_EQ(get_k(3), (std::vector<std::vector<GateTarget>>{
{GateTarget::qubit(0)},
{GateTarget::qubit(2)},
}));
ASSERT_EQ(get_k(4), (std::vector<std::vector<GateTarget>>{
}));
ASSERT_EQ(get_k(5), (std::vector<std::vector<GateTarget>>{
{GateTarget::qubit(0), GateTarget::qubit(1)},
{GateTarget::qubit(2), GateTarget::qubit(3)},
}));
ASSERT_EQ(get_k(6), (std::vector<std::vector<GateTarget>>{
{GateTarget::qubit(3), GateTarget::qubit(5)},
}));
ASSERT_EQ(get_k(7), (std::vector<std::vector<GateTarget>>{
}));
ASSERT_EQ(get_k(8), (std::vector<std::vector<GateTarget>>{
{GateTarget::x(0), GateTarget::combiner(), GateTarget::x(1), GateTarget::combiner(), GateTarget::z(2)},
{GateTarget::z(7)},
{GateTarget::x(5), GateTarget::combiner(), GateTarget::x(9)},
}));
ASSERT_EQ(get_k(9), (std::vector<std::vector<GateTarget>>{
{GateTarget::z(5)},
}));
ASSERT_EQ(get_k(0), (std::vector<std::vector<GateTarget>>{}));
ASSERT_EQ(get_k(1), (std::vector<std::vector<GateTarget>>{}));
ASSERT_EQ(
get_k(2),
(std::vector<std::vector<GateTarget>>{
{GateTarget::qubit(1)},
}));
ASSERT_EQ(
get_k(3),
(std::vector<std::vector<GateTarget>>{
{GateTarget::qubit(0)},
{GateTarget::qubit(2)},
}));
ASSERT_EQ(get_k(4), (std::vector<std::vector<GateTarget>>{}));
ASSERT_EQ(
get_k(5),
(std::vector<std::vector<GateTarget>>{
{GateTarget::qubit(0), GateTarget::qubit(1)},
{GateTarget::qubit(2), GateTarget::qubit(3)},
}));
ASSERT_EQ(
get_k(6),
(std::vector<std::vector<GateTarget>>{
{GateTarget::qubit(3), GateTarget::qubit(5)},
}));
ASSERT_EQ(get_k(7), (std::vector<std::vector<GateTarget>>{}));
ASSERT_EQ(
get_k(8),
(std::vector<std::vector<GateTarget>>{
{GateTarget::x(0), GateTarget::combiner(), GateTarget::x(1), GateTarget::combiner(), GateTarget::z(2)},
{GateTarget::z(7)},
{GateTarget::x(5), GateTarget::combiner(), GateTarget::x(9)},
}));
ASSERT_EQ(
get_k(9),
(std::vector<std::vector<GateTarget>>{
{GateTarget::z(5)},
}));
}

TEST(circuit_instruction, for_combined_targets_works_on_all) {
Expand Down
3 changes: 2 additions & 1 deletion src/stim/circuit/circuit_repeat_block.pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ Circuit CircuitRepeatBlock::body_copy() {
return body;
}
bool CircuitRepeatBlock::operator==(const CircuitRepeatBlock &other) const {
return repeat_count == other.repeat_count && body == other.body && pybind11::cast<std::string_view>(tag) == pybind11::cast<std::string_view>(other.tag);
return repeat_count == other.repeat_count && body == other.body &&
pybind11::cast<std::string_view>(tag) == pybind11::cast<std::string_view>(other.tag);
}
bool CircuitRepeatBlock::operator!=(const CircuitRepeatBlock &other) const {
return !(*this == other);
Expand Down
23 changes: 10 additions & 13 deletions src/stim/circuit/gate_decomposition.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ void stim::decompose_mpp_operation(
}
{
ConjugateBySelfInverse c1(CircuitInstruction(GateType::H, {}, h_xz, mpp_op.tag), do_instruction_callback);
ConjugateBySelfInverse c2(CircuitInstruction(GateType::H_YZ, {}, h_yz, mpp_op.tag), do_instruction_callback);
ConjugateBySelfInverse c2(
CircuitInstruction(GateType::H_YZ, {}, h_yz, mpp_op.tag), do_instruction_callback);
ConjugateBySelfInverse c3(CircuitInstruction(GateType::CX, {}, cnot, mpp_op.tag), do_instruction_callback);
do_instruction_callback(CircuitInstruction(GateType::M, mpp_op.args, meas, mpp_op.tag));
}
Expand Down Expand Up @@ -247,12 +248,13 @@ void stim::decompose_pair_instruction_into_disjoint_segments(
size_t num_flushed = 0;
size_t cur_index = 0;
auto flush = [&]() {
callback(CircuitInstruction{
inst.gate_type,
inst.args,
inst.targets.sub(num_flushed, cur_index),
inst.tag,
});
callback(
CircuitInstruction{
inst.gate_type,
inst.args,
inst.targets.sub(num_flushed, cur_index),
inst.tag,
});
used_as_control.clear();
num_flushed = cur_index;
};
Expand All @@ -279,12 +281,7 @@ void stim::for_each_disjoint_target_segment_in_instruction_reversed(
size_t cur_end = inst.targets.size();
size_t cur_start = inst.targets.size();
auto flush = [&]() {
callback(CircuitInstruction(
inst.gate_type,
inst.args,
inst.targets.sub(cur_start, cur_end),
inst.tag
));
callback(CircuitInstruction(inst.gate_type, inst.args, inst.targets.sub(cur_start, cur_end), inst.tag));
workspace.clear();
cur_end = cur_start;
};
Expand Down
Loading

0 comments on commit e6fd563

Please sign in to comment.