diff --git a/src/stim/circuit/circuit.cc b/src/stim/circuit/circuit.cc index 0c8ca2678..13c1b3b47 100644 --- a/src/stim/circuit/circuit.cc +++ b/src/stim/circuit/circuit.cc @@ -270,8 +270,8 @@ void Circuit::append_from_text(std::string_view text) { READ_CONDITION::READ_UNTIL_END_OF_FILE); } -void Circuit::safe_append(const CircuitInstruction &operation) { - safe_append(operation.gate_type, operation.targets, operation.args); +void Circuit::safe_append(const CircuitInstruction &operation, bool block_fusion) { + safe_append(operation.gate_type, operation.targets, operation.args, block_fusion); } void Circuit::safe_append_ua(std::string_view gate_name, const std::vector &targets, double singleton_arg) { @@ -299,7 +299,7 @@ void Circuit::safe_append_u( safe_append(gate.id, converted, args); } -void Circuit::safe_append(GateType gate_type, SpanRef targets, SpanRef args) { +void Circuit::safe_append(GateType gate_type, SpanRef targets, SpanRef args, bool block_fusion) { auto flags = GATE_DATA[gate_type].flags; if (flags & GATE_IS_BLOCK) { throw std::invalid_argument("Can't append a block like a normal operation."); @@ -312,7 +312,7 @@ void Circuit::safe_append(GateType gate_type, SpanRef targets, to_add.args = arg_buf.take_copy(to_add.args); to_add.targets = target_buf.take_copy(to_add.targets); - if (!operations.empty() && operations.back().can_fuse(to_add)) { + if (!block_fusion && !operations.empty() && operations.back().can_fuse(to_add)) { // Extend targets of last gate. fuse_data(operations.back().targets, to_add.targets, target_buf); } else { diff --git a/src/stim/circuit/circuit.h b/src/stim/circuit/circuit.h index 0fdb4d7c2..cf6718937 100644 --- a/src/stim/circuit/circuit.h +++ b/src/stim/circuit/circuit.h @@ -105,14 +105,14 @@ struct Circuit { Circuit &operator*=(uint64_t repetitions); /// Safely adds an operation at the end of the circuit, copying its data into the circuit's jagged data as needed. - void safe_append(const CircuitInstruction &operation); + void safe_append(const CircuitInstruction &operation, bool block_fusion = false); /// Safely adds an operation at the end of the circuit, copying its data into the circuit's jagged data as needed. void safe_append_ua(std::string_view gate_name, const std::vector &targets, double singleton_arg); /// Safely adds an operation at the end of the circuit, copying its data into the circuit's jagged data as needed. void safe_append_u( std::string_view gate_name, const std::vector &targets, const std::vector &args = {}); /// Safely adds an operation at the end of the circuit, copying its data into the circuit's jagged data as needed. - void safe_append(GateType gate_type, SpanRef targets, SpanRef args); + void safe_append(GateType gate_type, SpanRef targets, SpanRef args, bool block_fusion = false); /// Safely copies a repeat block to the end of the circuit. void append_repeat_block(uint64_t repeat_count, const Circuit &body); /// Safely moves a repeat block to the end of the circuit. diff --git a/src/stim/simulators/transform_without_feedback.cc b/src/stim/simulators/transform_without_feedback.cc index 908b92816..24151906b 100644 --- a/src/stim/simulators/transform_without_feedback.cc +++ b/src/stim/simulators/transform_without_feedback.cc @@ -127,7 +127,7 @@ struct WithoutFeedbackHelper { if (GATE_DATA[op.gate_type].flags & GATE_CAN_TARGET_BITS) { undo_feedback_capable_pcp_operation(op); } else { - reversed_semi_flattened_output.safe_append(op); + reversed_semi_flattened_output.safe_append(op, true); tracker.undo_gate(op); } } diff --git a/src/stim/simulators/transform_without_feedback.test.cc b/src/stim/simulators/transform_without_feedback.test.cc index 7743d4e9a..85071f2d4 100644 --- a/src/stim/simulators/transform_without_feedback.test.cc +++ b/src/stim/simulators/transform_without_feedback.test.cc @@ -144,3 +144,33 @@ TEST(circuit_with_inlined_feedback, mpp) { DETECTOR rec[-3] rec[-1] )CIRCUIT")); } + +TEST(circuit_with_inlined_feedback, interleaved_feedback_does_not_reorder_operations) { + ASSERT_EQ(circuit_with_inlined_feedback(Circuit(R"CIRCUIT( + H 0 + CZ + H 1 + )CIRCUIT")), Circuit(R"CIRCUIT( + H 0 1 + )CIRCUIT")); + + ASSERT_EQ(circuit_with_inlined_feedback(Circuit(R"CIRCUIT( + M 0 + CX + M 1 + )CIRCUIT")), Circuit(R"CIRCUIT( + M 0 1 + )CIRCUIT")); + + ASSERT_EQ(circuit_with_inlined_feedback(Circuit(R"CIRCUIT( + M 0 1 + CX + M 2 + CX rec[-1] 3 + M 3 + DETECTOR rec[-1] + )CIRCUIT")), Circuit(R"CIRCUIT( + M 0 1 2 3 + DETECTOR rec[-2] rec[-1] + )CIRCUIT")); +}