Skip to content

Commit

Permalink
Merge branch 'main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Strilanc authored Jan 23, 2025
2 parents bc991ea + 3751bef commit 874192b
Show file tree
Hide file tree
Showing 29 changed files with 495 additions and 320 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -453,16 +453,16 @@ jobs:
- run: pytest glue/zx
- run: dev/doctest_proper.py --module stimzx
test_stimjs:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: mymindstorm/setup-emsdk@v14
with:
version: 2.0.18
version: 4.0.1
actions-cache-folder: 'emsdk-cache'
- uses: actions/setup-node@v1
- uses: actions/setup-node@v4
with:
node-version: 16.x
node-version: 18.x
- run: npm install
- run: bash glue/javascript/build_wasm.sh
- run: node puppeteer_run_tests.js
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ venv
.cmake/*
coverage/*
cmake-build-debug-coverage/*
# clangd generated files
compile_commands.json
.cache
build.ninja
.ninja_deps
.ninja_log
.pytest_cache
node_modules
MODULE.bazel.lock
116 changes: 0 additions & 116 deletions MODULE.bazel.lock

This file was deleted.

25 changes: 25 additions & 0 deletions doc/gates.md
Original file line number Diff line number Diff line change
Expand Up @@ -3344,6 +3344,15 @@ determining the expected value, and `X_ERROR` is noise, causing deviations from
It is not recommended for the measurement set of an observable to have inconsistent parity. For example, the
circuit-to-detector-error-model conversion will refuse to operate on circuits containing such observables.

In addition to targeting measurements, observables can target Pauli operators. This has no effect when running the
quantum computation, but is used when configuring the decoder. For example, when performing a logical Z initialization,
it allows a logical X operator to be introduced (by marking its Pauli terms) despite the fact that it anticommutes
with the initialization. In practice, when physically sampling a circuit or simulating sampling its measurements and
then computing the observables from the measurements, these Pauli terms are effectively ignored. However, they affect
detection event simulations and affect whether the observable is included in errors in the detector error model. This
makes it easier to benchmark all observables of a code, without having to introduce noiseless qubits entangled with the
logical qubit to avoid the testing of the X observable anticommuting with the testing of the Z observable.

Parens Arguments:

A non-negative integer specifying the index of the logical observable to add the measurement records to.
Expand All @@ -3370,6 +3379,22 @@ Example:
# ...and the one before that.
OBSERVABLE_INCLUDE(1) rec[-2]

# Unphysically tracking two anticommuting observables of a 2x2 surface code.
QUBIT_COORDS(0, 0) 0
QUBIT_COORDS(1, 0) 1
QUBIT_COORDS(0, 1) 2
QUBIT_COORDS(1, 1) 3
OBSERVABLE_INCLUDE(0) X0 X1
OBSERVABLE_INCLUDE(1) Z0 Z2
MPP X0*X1*X2*X3 Z0*Z1 Z2*Z3
DEPOLARIZE1(0.001) 0 1 2 3
MPP X0*X1*X2*X3 Z0*Z1 Z2*Z3
DETECTOR rec[-1] rec[-4]
DETECTOR rec[-2] rec[-5]
DETECTOR rec[-3] rec[-6]
OBSERVABLE_INCLUDE(0) X0 X1
OBSERVABLE_INCLUDE(1) Z0 Z2

<a name="QUBIT_COORDS"></a>
### The 'QUBIT_COORDS' Instruction

Expand Down
2 changes: 2 additions & 0 deletions src/stim/circuit/circuit.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1807,12 +1807,14 @@ Circuit stim::generate_test_circuit_with_all_operations() {
DETECTOR(1, 2, 3) rec[-1]
OBSERVABLE_INCLUDE(0) rec[-1]
MPAD 0 1 0
OBSERVABLE_INCLUDE(1) Z2 Z3
TICK
# Inverted measurements.
MRX !0
MY !1
MZZ !2 3
OBSERVABLE_INCLUDE(1) rec[-1]
MYY !4 !5
MPP X6*!Y7*Z8
TICK
Expand Down
14 changes: 11 additions & 3 deletions src/stim/circuit/circuit_instruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,17 @@ void CircuitInstruction::validate() const {
valid_target_mask |= TARGET_RECORD_BIT | TARGET_SWEEP_BIT;
}
if (gate.flags & GATE_ONLY_TARGETS_MEASUREMENT_RECORD) {
for (GateTarget q : targets) {
if (!(q.data & TARGET_RECORD_BIT)) {
throw std::invalid_argument("Gate " + std::string(gate.name) + " only takes rec[-k] targets.");
if (gate.flags & GATE_TARGETS_PAULI_STRING) {
for (GateTarget q : targets) {
if (!q.is_measurement_record_target() && !q.is_pauli_target()) {
throw std::invalid_argument("Gate " + std::string(gate.name) + " only takes measurement record targets and Pauli targets (rec[-k], Xk, Yk, Zk).");
}
}
} else {
for (GateTarget q : targets) {
if (!q.is_measurement_record_target()) {
throw std::invalid_argument("Gate " + std::string(gate.name) + " only takes measurement record targets (rec[-k]).");
}
}
}
} else if (gate.flags & GATE_TARGETS_PAULI_STRING) {
Expand Down
14 changes: 0 additions & 14 deletions src/stim/cmd/command_m2d.cc
Original file line number Diff line number Diff line change
@@ -1,17 +1,3 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "stim/cmd/command_m2d.h"

#include "command_help.h"
Expand Down
27 changes: 27 additions & 0 deletions src/stim/cmd/command_m2d.test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,30 @@ TEST(command_m2d, m2d_obs_size_misalign_11_obs) {
trim(std::string(1024, '0') + "\n"));
ASSERT_EQ(tmp_obs.read_contents(), "00000000000\n");
}

TEST(command_m2d, unphysical_observable_annotations) {
RaiiTempNamedFile tmp_circuit(R"CIRCUIT(
QUBIT_COORDS(0, 0) 0
QUBIT_COORDS(1, 0) 1
QUBIT_COORDS(0, 1) 2
QUBIT_COORDS(1, 1) 3
OBSERVABLE_INCLUDE(0) X0 X1
OBSERVABLE_INCLUDE(1) Z0 Z2
MPP X0*X1*X2*X3 Z0*Z1 Z2*Z3
DEPOLARIZE1(0.001) 0 1 2 3
MPP X0*X1*X2*X3 Z0*Z1 Z2*Z3
DETECTOR rec[-1] rec[-4]
DETECTOR rec[-2] rec[-5]
DETECTOR rec[-3] rec[-6]
OBSERVABLE_INCLUDE(0) X0 X1
OBSERVABLE_INCLUDE(1) Z0 Z2
)CIRCUIT");
RaiiTempNamedFile tmp_obs;

ASSERT_EQ(
trim(run_captured_stim_main(
{"m2d", "--in_format=01", "--obs_out", tmp_obs.path.c_str(), "--circuit", tmp_circuit.path.c_str()},
"000000\n100100\n000110\n")),
trim("000\n000\n011\n"));
ASSERT_EQ(tmp_obs.read_contents(), "00\n00\n00\n");
}
9 changes: 6 additions & 3 deletions src/stim/diagram/circuit_timeline_helper.cc
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#include "stim/diagram/circuit_timeline_helper.h"

#include "stim/diagram/diagram_util.h"

using namespace stim;
using namespace stim_draw_internal;

void CircuitTimelineHelper::skip_loop_iterations(CircuitTimelineLoopData loop_data, uint64_t skipped_reps) {
void CircuitTimelineHelper::skip_loop_iterations(const CircuitTimelineLoopData &loop_data, uint64_t skipped_reps) {
if (loop_data.num_repetitions > 0) {
vec_pad_add_mul(cur_coord_shift, loop_data.shift_per_iteration, skipped_reps);
measure_offset += loop_data.measurements_per_iteration * skipped_reps;
Expand Down Expand Up @@ -95,6 +93,11 @@ GateTarget CircuitTimelineHelper::rec_to_qubit(const GateTarget &target) {
}

GateTarget CircuitTimelineHelper::pick_pseudo_target_representing_measurements(const CircuitInstruction &op) {
for (const auto &t : op.targets) {
if (t.is_qubit_target() || t.is_pauli_target()) {
return t;
}
}
// First check if coordinates prefix-match a qubit's coordinates.
if (!op.args.empty()) {
auto coords = shifted_coordinates_in_workspace(op.args);
Expand Down
2 changes: 1 addition & 1 deletion src/stim/diagram/circuit_timeline_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ struct CircuitTimelineHelper {

stim::GateTarget rec_to_qubit(const stim::GateTarget &target);
stim::GateTarget pick_pseudo_target_representing_measurements(const stim::CircuitInstruction &op);
void skip_loop_iterations(CircuitTimelineLoopData loop_data, uint64_t skipped_reps);
void skip_loop_iterations(const CircuitTimelineLoopData &loop_data, uint64_t skipped_reps);
void do_record_measure_result(uint32_t target_qubit);
void do_repeat_block(const stim::Circuit &circuit, const stim::CircuitInstruction &op);
void do_next_operation(const stim::Circuit &circuit, const stim::CircuitInstruction &op);
Expand Down
Loading

0 comments on commit 874192b

Please sign in to comment.