diff --git a/file_lists/source_files_no_main b/file_lists/source_files_no_main index 0a5ecae32..4efbd8c4d 100644 --- a/file_lists/source_files_no_main +++ b/file_lists/source_files_no_main @@ -1,14 +1 @@ -src/stim/gates/gate_data_annotations.cc -src/stim/gates/gate_data_blocks.cc -src/stim/gates/gate_data_collapsing.cc -src/stim/gates/gate_data_controlled.cc -src/stim/gates/gate_data_hada.cc -src/stim/gates/gate_data_heralded.cc -src/stim/gates/gate_data_noisy.cc -src/stim/gates/gate_data_pair_measure.cc -src/stim/gates/gate_data_pauli.cc -src/stim/gates/gate_data_period_3.cc -src/stim/gates/gate_data_period_4.cc -src/stim/gates/gate_data_pp.cc -src/stim/gates/gate_data_swaps.cc src/stim/gates/gates.cc diff --git a/src/stim/gates/gate_data_annotations.cc b/src/stim/gates/gate_data_annotations.cc deleted file mode 100644 index b71301ccc..000000000 --- a/src/stim/gates/gate_data_annotations.cc +++ /dev/null @@ -1,358 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -void GateDataMap::add_gate_data_annotations(bool &failed) { - add_gate( - failed, - Gate{ - .name = "DETECTOR", - .id = GateType::DETECTOR, - .best_candidate_inverse_id = GateType::DETECTOR, - .arg_count = ARG_COUNT_SYGIL_ANY, - .flags = - (GateFlags)(GATE_ONLY_TARGETS_MEASUREMENT_RECORD | GATE_IS_NOT_FUSABLE | GATE_HAS_NO_EFFECT_ON_QUBITS), - .category = "Z_Annotations", - .help = R"MARKDOWN( -Annotates that a set of measurements can be used to detect errors, because the set's parity should be deterministic. - -Note that it is not necessary to say whether the measurement set's parity is even or odd; all that matters is that the -parity should be *consistent* when running the circuit and omitting all noisy operations. Note that, for example, this -means that even though `X` and `X_ERROR(1)` have equivalent effects on the measurements making up a detector, they have -differing effects on the detector (because `X` is intended, determining the expected value, and `X_ERROR` is noise, -causing deviations from the expected value). - -Detectors are ignored when sampling measurements, but produce results when sampling detection events. In detector -sampling mode, each detector produces a result bit (where 0 means "measurement set had expected parity" and 1 means -"measurement set had incorrect parity"). When converting a circuit into a detector error model, errors are grouped based -on the detectors they flip (the "symptoms" of the error) and the observables they flip (the "frame changes" of the -error). - -It is permitted, though not recommended, for the measurement set given to a `DETECTOR` instruction to have inconsistent -parity. When a detector's measurement set is inconsistent, the detector is called a "gauge detector" and the expected -parity of the measurement set is chosen arbitrarily (in an implementation-defined way). Some circuit analysis tools -(such as the circuit-to-detector-error-model conversion) will by default refuse to process circuits containing gauge -detectors. Gauge detectors produce random results when sampling detection events, though these results will be -appropriately correlated with other gauge detectors. For example, if `DETECTOR rec[-1]` and `DETECTOR rec[-2]` are gauge -detectors but `DETECTOR rec[-1] rec[-2]` is not, then under noiseless execution the two gauge detectors would either -always produce the same result or always produce opposite results. - -Detectors can specify coordinates using their parens arguments. Coordinates have no effect on simulations, but can be -useful to tools consuming the circuit. For example, a tool drawing how the detectors in a circuit relate to each other -can use the coordinates as hints for where to place the detectors in the drawing. - -Parens Arguments: - - Optional. - Coordinate metadata, relative to the current coordinate offset accumulated from `SHIFT_COORDS` instructions. - Can be any number of coordinates from 1 to 16. - There is no required convention for which coordinate is which. - -Targets: - - The measurement records to XOR together to get the deterministic-under-noiseless-execution parity. - -Example: - - R 0 - X_ERROR(0.1) 0 - M 0 # This measurement is always False under noiseless execution. - # Annotate that most recent measurement should be deterministic. - DETECTOR rec[-1] - - R 0 - X 0 - X_ERROR(0.1) 0 - M 0 # This measurement is always True under noiseless execution. - # Annotate that most recent measurement should be deterministic. - DETECTOR rec[-1] - - R 0 1 - H 0 - CNOT 0 1 - DEPOLARIZE2(0.001) 0 1 - M 0 1 # These two measurements are always equal under noiseless execution. - # Annotate that the parity of the previous two measurements should be consistent. - DETECTOR rec[-1] rec[-2] - - # A series of trivial detectors with hinted coordinates along the diagonal line Y = 2X + 3. - REPEAT 100 { - R 0 - M 0 - SHIFT_COORDS(1, 2) - DETECTOR(0, 3) rec[-1] - } -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "OBSERVABLE_INCLUDE", - .id = GateType::OBSERVABLE_INCLUDE, - .best_candidate_inverse_id = GateType::OBSERVABLE_INCLUDE, - .arg_count = 1, - .flags = (GateFlags)(GATE_ONLY_TARGETS_MEASUREMENT_RECORD | GATE_IS_NOT_FUSABLE | - GATE_ARGS_ARE_UNSIGNED_INTEGERS | GATE_HAS_NO_EFFECT_ON_QUBITS), - .category = "Z_Annotations", - .help = R"MARKDOWN( -Adds measurement records to a specified logical observable. - -A potential point of confusion here is that Stim's notion of a logical observable is nothing more than a set of -measurements, potentially spanning across the entire circuit, that together produce a deterministic result. It's more -akin to the "boundary of a parity sheet" in a topological spacetime diagram than it is to the notion of a qubit -observable. For example, consider a surface code memory experiment that initializes a logical |0>, preserves the state -noise, and eventually performs a logical Z basis measurement. The circuit representing this experiment would use -`OBSERVABLE_INCLUDE` instructions to specifying which physical measurements within the logical Z basis measurement -should be XOR'd together to get the logical measurement result. This effectively identifies the logical Z observable. -But the circuit would *not* declare an X observable, because the X observable is not deterministic in a Z basis memory -experiment; it has no corresponding deterministic measurement set. - -Logical observables are ignored when sampling measurements, but can produce results (if requested) when sampling -detection events. In detector sampling mode, each observable can produce a result bit (where 0 means "measurement set -had expected parity" and 1 means "measurement set had incorrect parity"). When converting a circuit into a detector -error model, errors are grouped based on the detectors they flip (the "symptoms" of the error) and the observables they -flip (the "frame changes" of the error). - -Another potential point of confusion is that when sampling logical measurement results, as part of sampling detection -events in the circuit, the reported results are not measurements of the logical observable but rather whether those -measurement results *were flipped*. This has significant simulation speed benefits, and also makes it so that it is not -necessary to say whether the logical measurement result is supposed to be False or True. Note that, for example, this -means that even though `X` and `X_ERROR(1)` have equivalent effects on the measurements making up an observable, they -have differing effects on the reported value of an observable when sampling detection events (because `X` is intended, -determining the expected value, and `X_ERROR` is noise, causing deviations from the expected value). - -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. - -Parens Arguments: - - A non-negative integer specifying the index of the logical observable to add the measurement records to. - -Targets: - - The measurement records to add to the specified observable. - -Example: - - R 0 1 - H 0 - CNOT 0 1 - M 0 1 - # Observable 0 is the parity of the previous two measurements. - OBSERVABLE_INCLUDE(0) rec[-1] rec[-2] - - R 0 1 - H 0 - CNOT 0 1 - M 0 1 - # Observable 1 is the parity of the previous measurement... - OBSERVABLE_INCLUDE(1) rec[-1] - # ...and the one before that. - OBSERVABLE_INCLUDE(1) rec[-2] -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "TICK", - .id = GateType::TICK, - .best_candidate_inverse_id = GateType::TICK, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_NOT_FUSABLE | GATE_TAKES_NO_TARGETS | GATE_HAS_NO_EFFECT_ON_QUBITS), - .category = "Z_Annotations", - .help = R"MARKDOWN( -Annotates the end of a layer of gates, or that time is advancing. - -This instruction is not necessary, it has no effect on simulations, but it can be used by tools that are transforming or -visualizing the circuit. For example, a tool that adds noise to a circuit may include cross-talk terms that require -knowing whether or not operations are happening in the same time step or not. - -TICK instructions are added, and checked for, by `stimcirq` in order to preserve the moment structure of cirq circuits -converted between stim circuits and cirq circuits. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - This instruction takes no targets. - -Example: - - # First time step. - H 0 - CZ 1 2 - TICK - - # Second time step. - H 1 - TICK - - # Empty time step. - TICK -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "QUBIT_COORDS", - .id = GateType::QUBIT_COORDS, - .best_candidate_inverse_id = GateType::QUBIT_COORDS, - .arg_count = ARG_COUNT_SYGIL_ANY, - .flags = (GateFlags)(GATE_IS_NOT_FUSABLE | GATE_HAS_NO_EFFECT_ON_QUBITS), - .category = "Z_Annotations", - .help = R"MARKDOWN( -Annotates the location of a qubit. - -Coordinates are not required and have no effect on simulations, but can be useful to tools consuming the circuit. For -example, a tool drawing the circuit can use the coordinates as hints for where to place the qubits in the drawing. -`stimcirq` uses `QUBIT_COORDS` instructions to preserve `cirq.LineQubit` and `cirq.GridQubit` coordinates when -converting between stim circuits and cirq circuits - -A qubit's coordinates can be specified multiple times, with the intended interpretation being that the qubit is at the -location of the most recent assignment. For example, this could be used to indicate a simulated qubit is iteratively -playing the role of many physical qubits. - -Parens Arguments: - - Optional. - The latest coordinates of the qubit, relative to accumulated offsets from `SHIFT_COORDS` instructions. - Can be any number of coordinates from 1 to 16. - There is no required convention for which coordinate is which. - -Targets: - - The qubit or qubits the coordinates apply to. - -Example: - - # Annotate that qubits 0 to 3 are at the corners of a square. - QUBIT_COORDS(0, 0) 0 - QUBIT_COORDS(0, 1) 1 - QUBIT_COORDS(1, 0) 2 - QUBIT_COORDS(1, 1) 3 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "SHIFT_COORDS", - .id = GateType::SHIFT_COORDS, - .best_candidate_inverse_id = GateType::SHIFT_COORDS, - .arg_count = ARG_COUNT_SYGIL_ANY, - .flags = (GateFlags)(GATE_IS_NOT_FUSABLE | GATE_TAKES_NO_TARGETS | GATE_HAS_NO_EFFECT_ON_QUBITS), - .category = "Z_Annotations", - .help = R"MARKDOWN( -Accumulates offsets that affect qubit coordinates and detector coordinates. - -Note: when qubit/detector coordinates use fewer dimensions than SHIFT_COORDS, the offsets from the additional dimensions -are ignored (i.e. not specifying a dimension is different from specifying it to be 0). - -See also: `QUBIT_COORDS`, `DETECTOR`. - -Parens Arguments: - - Offsets to add into the current coordinate offset. - Can be any number of coordinate offsets from 1 to 16. - There is no required convention for which coordinate is which. - -Targets: - - This instruction takes no targets. - -Example: - - SHIFT_COORDS(500.5) - QUBIT_COORDS(1510) 0 # Actually at 2010.5 - SHIFT_COORDS(1500) - QUBIT_COORDS(11) 1 # Actually at 2011.5 - QUBIT_COORDS(10.5) 2 # Actually at 2011.0 - - # Declare some detectors with coordinates along a diagonal line. - REPEAT 1000 { - CNOT 0 2 - CNOT 1 2 - MR 2 - DETECTOR(10.5, 0) rec[-1] rec[-2] # Actually at (2011.0, iteration_count). - SHIFT_COORDS(0, 1) # Advance 2nd coordinate to track loop iterations. - } -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "MPAD", - .id = GateType::MPAD, - .best_candidate_inverse_id = GateType::MPAD, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_PRODUCES_RESULTS | GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "Z_Annotations", - .help = R"MARKDOWN( -Pads the measurement record with the listed measurement results. - -This can be useful for ensuring measurements are aligned to word boundaries, or that the -number of measurement bits produced per circuit layer is always the same even if the number -of measured qubits varies. - -Parens Arguments: - - If no parens argument is given, the padding bits are recorded perfectly. - If one parens argument is given, the padding bits are recorded noisily. - The argument is the probability of recording the wrong result. - -Targets: - - Each target is a measurement result to add. - Targets should be the value 0 or the value 1. - -Examples: - - # Append a False result to the measurement record. - MPAD 0 - - # Append a True result to the measurement record. - MPAD 1 - - # Append a series of results to the measurement record. - MPAD 0 0 1 0 1 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); -} diff --git a/src/stim/gates/gate_data_blocks.cc b/src/stim/gates/gate_data_blocks.cc deleted file mode 100644 index d48062c8f..000000000 --- a/src/stim/gates/gate_data_blocks.cc +++ /dev/null @@ -1,62 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -void GateDataMap::add_gate_data_blocks(bool &failed) { - add_gate( - failed, - Gate{ - .name = "REPEAT", - .id = GateType::REPEAT, - .best_candidate_inverse_id = GateType::REPEAT, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_BLOCK | GATE_IS_NOT_FUSABLE), - .category = "Y_Control Flow", - .help = R"MARKDOWN( -Repeats the instructions in its body N times. - -Currently, repetition counts of 0 are not allowed because they create corner cases with ambiguous resolutions. -For example, if a logical observable is only given measurements inside a repeat block with a repetition count of 0, it's -ambiguous whether the output of sampling the logical observables includes a bit for that logical observable. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - A positive integer in [1, 10^18] specifying the number of repetitions. - -Example: - - REPEAT 2 { - CNOT 0 1 - CNOT 2 1 - M 1 - } - REPEAT 10000000 { - CNOT 0 1 - CNOT 2 1 - M 1 - DETECTOR rec[-1] rec[-3] - } -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); -} diff --git a/src/stim/gates/gate_data_collapsing.cc b/src/stim/gates/gate_data_collapsing.cc deleted file mode 100644 index 8b5e04f2c..000000000 --- a/src/stim/gates/gate_data_collapsing.cc +++ /dev/null @@ -1,529 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -void GateDataMap::add_gate_data_collapsing(bool &failed) { - // ===================== Measure Gates. ============================ - add_gate( - failed, - Gate{ - .name = "MX", - .id = GateType::MX, - .best_candidate_inverse_id = GateType::MX, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -X-basis measurement. -Projects each target qubit into `|+>` or `|->` and reports its value (false=`|+>`, true=`|->`). - -Parens Arguments: - - If no parens argument is given, the measurement is perfect. - If one parens argument is given, the measurement result is noisy. - The argument is the probability of returning the wrong result. - -Targets: - - The qubits to measure in the X basis. - Prefixing a qubit target with `!` flips its reported measurement result. - -Examples: - - # Measure qubit 5 in the X basis, and append the result into the measurement record. - MX 5 - - # Measure qubit 5 in the X basis, and append the INVERSE of its result into the measurement record. - MX !5 - - # Do a noisy measurement where the result put into the measurement record is wrong 1% of the time. - MX(0.01) 5 - - # Measure multiple qubits in the X basis, putting 3 bits into the measurement record. - MX 2 3 5 - - # Perform multiple noisy measurements. Each measurement fails independently with 2% probability. - MX(0.02) 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"X -> rec[-1]", "X -> +X"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -M 0 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "MY", - .id = GateType::MY, - .best_candidate_inverse_id = GateType::MY, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -Y-basis measurement. -Projects each target qubit into `|i>` or `|-i>` and reports its value (false=`|i>`, true=`|-i>`). - -Parens Arguments: - - If no parens argument is given, the measurement is perfect. - If one parens argument is given, the measurement result is noisy. - The argument is the probability of returning the wrong result. - -Targets: - - The qubits to measure in the Y basis. - Prefixing a qubit target with `!` flips its reported measurement result. - -Examples: - - # Measure qubit 5 in the Y basis, and append the result into the measurement record. - MY 5 - - # Measure qubit 5 in the Y basis, and append the INVERSE of its result into the measurement record. - MY !5 - - # Do a noisy measurement where the result put into the measurement record is wrong 1% of the time. - MY(0.01) 5 - - # Measure multiple qubits in the X basis, putting 3 bits into the measurement record. - MY 2 3 5 - - # Perform multiple noisy measurements. Each measurement fails independently with 2% probability. - MY(0.02) 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"Y -> rec[-1]", "Y -> +Y"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -H 0 -M 0 -H 0 -S 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "M", - .id = GateType::M, - .best_candidate_inverse_id = GateType::M, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -Z-basis measurement. -Projects each target qubit into `|0>` or `|1>` and reports its value (false=`|0>`, true=`|1>`). - -Parens Arguments: - - If no parens argument is given, the measurement is perfect. - If one parens argument is given, the measurement result is noisy. - The argument is the probability of returning the wrong result. - -Targets: - - The qubits to measure in the Z basis. - Prefixing a qubit target with `!` flips its reported measurement result. - -Examples: - - # Measure qubit 5 in the Z basis, and append the result into the measurement record. - M 5 - - # 'MZ' is the same as 'M'. This also measures qubit 5 in the Z basis. - MZ 5 - - # Measure qubit 5 in the Z basis, and append the INVERSE of its result into the measurement record. - MZ !5 - - # Do a noisy measurement where the result put into the measurement record is wrong 1% of the time. - MZ(0.01) 5 - - # Measure multiple qubits in the Z basis, putting 3 bits into the measurement record. - MZ 2 3 5 - - # Perform multiple noisy measurements. Each measurement fails independently with 2% probability. - MZ(0.02) 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"Z -> rec[-1]", "Z -> +Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -M 0 -)CIRCUIT", - }); - - add_gate_alias(failed, "MZ", "M"); - - // ===================== Measure+Reset Gates. ============================ - add_gate( - failed, - Gate{ - .name = "MRX", - .id = GateType::MRX, - .best_candidate_inverse_id = GateType::MRX, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES | GATE_IS_RESET), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -X-basis demolition measurement (optionally noisy). -Projects each target qubit into `|+>` or `|->`, reports its value (false=`|+>`, true=`|->`), then resets to `|+>`. - -Parens Arguments: - - If no parens argument is given, the demolition measurement is perfect. - If one parens argument is given, the demolition measurement's result is noisy. - The argument is the probability of returning the wrong result. - The argument does not affect the fidelity of the reset. - -Targets: - - The qubits to measure and reset in the X basis. - Prefixing a qubit target with `!` flips its reported measurement result. - -Examples: - - # Measure qubit 5 in the X basis, reset it to the |+> state, append the measurement result into the measurement record. - MRX 5 - - # Demolition measure qubit 5 in the X basis, but append the INVERSE of its result into the measurement record. - MRX !5 - - # Do a noisy demolition measurement where the result put into the measurement record is wrong 1% of the time. - MRX(0.01) 5 - - # Demolition measure multiple qubits in the X basis, putting 3 bits into the measurement record. - MRX 2 3 5 - - # Perform multiple noisy demolition measurements. Each measurement result is flipped independently with 2% probability. - MRX(0.02) 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"X -> rec[-1]", "1 -> +X"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -M 0 -R 0 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "MRY", - .id = GateType::MRY, - .best_candidate_inverse_id = GateType::MRY, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES | GATE_IS_RESET), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -Y-basis demolition measurement (optionally noisy). -Projects each target qubit into `|i>` or `|-i>`, reports its value (false=`|i>`, true=`|-i>`), then resets to `|i>`. - -Parens Arguments: - - If no parens argument is given, the demolition measurement is perfect. - If one parens argument is given, the demolition measurement's result is noisy. - The argument is the probability of returning the wrong result. - The argument does not affect the fidelity of the reset. - -Targets: - - The qubits to measure and reset in the Y basis. - Prefixing a qubit target with `!` flips its reported measurement result. - -Examples: - - # Measure qubit 5 in the Y basis, reset it to the |i> state, append the measurement result into the measurement record. - MRY 5 - - # Demolition measure qubit 5 in the Y basis, but append the INVERSE of its result into the measurement record. - MRY !5 - - # Do a noisy demolition measurement where the result put into the measurement record is wrong 1% of the time. - MRY(0.01) 5 - - # Demolition measure multiple qubits in the Y basis, putting 3 bits into the measurement record. - MRY 2 3 5 - - # Perform multiple noisy demolition measurements. Each measurement result is flipped independently with 2% probability. - MRY(0.02) 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"Y -> rec[-1]", "1 -> +Y"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -H 0 -M 0 -R 0 -H 0 -S 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "MR", - .id = GateType::MR, - .best_candidate_inverse_id = GateType::MR, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES | GATE_IS_RESET), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -Z-basis demolition measurement (optionally noisy). -Projects each target qubit into `|0>` or `|1>`, reports its value (false=`|0>`, true=`|1>`), then resets to `|0>`. - -Parens Arguments: - - If no parens argument is given, the demolition measurement is perfect. - If one parens argument is given, the demolition measurement's result is noisy. - The argument is the probability of returning the wrong result. - The argument does not affect the fidelity of the reset. - -Targets: - - The qubits to measure and reset in the Z basis. - Prefixing a qubit target with `!` flips its reported measurement result. - -Examples: - - # Measure qubit 5 in the Z basis, reset it to the |0> state, append the measurement result into the measurement record. - MRZ 5 - - # MR is also a Z-basis demolition measurement. - MR 5 - - # Demolition measure qubit 5 in the Z basis, but append the INVERSE of its result into the measurement record. - MRZ !5 - - # Do a noisy demolition measurement where the result put into the measurement record is wrong 1% of the time. - MRZ(0.01) 5 - - # Demolition measure multiple qubits in the Z basis, putting 3 bits into the measurement record. - MRZ 2 3 5 - - # Perform multiple noisy demolition measurements. Each measurement result is flipped independently with 2% probability. - MRZ(0.02) 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"Z -> rec[-1]", "1 -> +Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -M 0 -R 0 -)CIRCUIT", - }); - - add_gate_alias(failed, "MRZ", "MR"); - - // ===================== Reset Gates. ============================ - add_gate( - failed, - Gate{ - .name = "RX", - .id = GateType::RX, - .best_candidate_inverse_id = GateType::MRX, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_RESET), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -X-basis reset. -Forces each target qubit into the `|+>` state by silently measuring it in the X basis and applying a `Z` gate if it ended up in the `|->` state. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - The qubits to reset in the X basis. - -Examples: - - # Reset qubit 5 into the |+> state. - RX 5 - - # Reset multiple qubits into the |+> state. - RX 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"1 -> +X"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -R 0 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "RY", - .id = GateType::RY, - .best_candidate_inverse_id = GateType::MRY, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_RESET), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -Y-basis reset. -Forces each target qubit into the `|i>` state by silently measuring it in the Y basis and applying an `X` gate if it ended up in the `|-i>` state. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - The qubits to reset in the Y basis. - -Examples: - - # Reset qubit 5 into the |i> state. - RY 5 - - # Reset multiple qubits into the |i> state. - RY 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"1 -> +Y"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -R 0 -H 0 -S 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "R", - .id = GateType::R, - .best_candidate_inverse_id = GateType::MR, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_RESET), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -Z-basis reset. -Forces each target qubit into the `|0>` state by silently measuring it in the Z basis and applying an `X` gate if it ended up in the `|1>` state. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - The qubits to reset in the Z basis. - -Examples: - - # Reset qubit 5 into the |0> state. - RZ 5 - - # R means the same thing as RZ. - R 5 - - # Reset multiple qubits into the |0> state. - RZ 2 3 5 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {"1 -> +Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -R 0 -)CIRCUIT", - }); - - add_gate_alias(failed, "RZ", "R"); - - add_gate( - failed, - Gate{ - .name = "MPP", - .id = GateType::MPP, - .best_candidate_inverse_id = GateType::MPP, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_PRODUCES_RESULTS | GATE_IS_NOISY | GATE_TARGETS_PAULI_STRING | - GATE_TARGETS_COMBINERS | GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "L_Collapsing Gates", - .help = R"MARKDOWN( -Measure Pauli products. - -Parens Arguments: - - Optional. - A single float specifying the probability of flipping each reported measurement result. - -Targets: - - A series of Pauli products to measure. - - Each Pauli product is a series of Pauli targets (`[XYZ]#`) separated by combiners (`*`). - Products can be negated by prefixing a Pauli target in the product with an inverter (`!`) - -Examples: - - # Measure the two-body +X1*Y2 observable. - MPP X1*Y2 - - # Measure the one-body -Z5 observable. - MPP !Z5 - - # Measure the two-body +X1*Y2 observable and also the three-body -Z3*Z4*Z5 observable. - MPP X1*Y2 !Z3*Z4*Z5 - - # Noisily measure +Z1+Z2 and +X1*X2 (independently flip each reported result 0.1% of the time). - MPP(0.001) Z1*Z2 X1*X2 - -)MARKDOWN", - .unitary_data = {}, - .flow_data = - { - "XYZ__ -> rec[-2]", - "___XX -> rec[-1]", - "X____ -> X____", - "_Y___ -> _Y___", - "__Z__ -> __Z__", - "___X_ -> ___X_", - "____X -> ____X", - "ZZ___ -> ZZ___", - "_XX__ -> _XX__", - "___ZZ -> ___ZZ", - }, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 1 1 1 -H 0 1 3 4 -CX 2 0 1 0 4 3 -M 0 3 -CX 2 0 1 0 4 3 -H 0 1 3 4 -S 1 -)CIRCUIT", - }); -} diff --git a/src/stim/gates/gate_data_controlled.cc b/src/stim/gates/gate_data_controlled.cc deleted file mode 100644 index 49ba28f83..000000000 --- a/src/stim/gates/gate_data_controlled.cc +++ /dev/null @@ -1,461 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -static constexpr std::complex i = std::complex(0, 1); - -void GateDataMap::add_gate_data_controlled(bool &failed) { - add_gate( - failed, - Gate{ - .name = "XCX", - .id = GateType::XCX, - .best_candidate_inverse_id = GateType::XCX, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The X-controlled X gate. -First qubit is the control, second qubit is the target. - -Applies an X gate to the target if the control is in the |-> state. - -Negates the amplitude of the |->|-> state. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = - {{0.5f, 0.5f, 0.5f, -0.5f}, - {0.5f, 0.5f, -0.5f, 0.5f}, - {0.5f, -0.5f, 0.5f, 0.5f}, - {-0.5f, 0.5f, 0.5f, 0.5f}}, - .flow_data = {"+XI", "+ZX", "+IX", "+XZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -CNOT 0 1 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "XCY", - .id = GateType::XCY, - .best_candidate_inverse_id = GateType::XCY, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The X-controlled Y gate. -First qubit is the control, second qubit is the target. - -Applies a Y gate to the target if the control is in the |-> state. - -Negates the amplitude of the |->|-i> state. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = - {{0.5f, 0.5f, -0.5f * i, 0.5f * i}, - {0.5f, 0.5f, 0.5f * i, -0.5f * i}, - {0.5f * i, -0.5f * i, 0.5f, 0.5f}, - {-0.5f * i, 0.5f * i, 0.5f, 0.5f}}, - .flow_data = {"+XI", "+ZY", "+XX", "+XZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -S 1 -S 1 -S 1 -CNOT 0 1 -H 0 -S 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "XCZ", - .id = GateType::XCZ, - .best_candidate_inverse_id = GateType::XCZ, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS | GATE_CAN_TARGET_BITS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The X-controlled Z gate. -Applies a Z gate to the target if the control is in the |-> state. -Equivalently: negates the amplitude of the |->|1> state. -Same as a CX gate, but with reversed qubit order. -The first qubit is the control, and the second qubit is the target. - -To perform a classically controlled X, replace the Z target with a `rec` -target like rec[-2]. - -To perform an I or X gate as configured by sweep data, replace the -Z target with a `sweep` target like sweep[3]. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. - -Example: - - # Bit flip qubit 5 controlled by qubit 2. - XCZ 5 2 - - # Perform CX 2 5 then CX 4 2. - XCZ 5 2 2 4 - - # Bit flip qubit 6 if the most recent measurement result was TRUE. - XCZ 6 rec[-1] - - # Bit flip qubits 7 and 8 conditioned on sweep configuration data. - XCZ 7 sweep[5] 8 sweep[5] -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}, {0, 0, 1, 0}}, - .flow_data = {"+XI", "+ZZ", "+XX", "+IZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -CNOT 1 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "YCX", - .id = GateType::YCX, - .best_candidate_inverse_id = GateType::YCX, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The Y-controlled X gate. -First qubit is the control, second qubit is the target. - -Applies an X gate to the target if the control is in the |-i> state. - -Negates the amplitude of the |-i>|-> state. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = - {{0.5f, -i * 0.5f, 0.5f, i * 0.5f}, - {i * 0.5f, 0.5f, -i * 0.5f, 0.5f}, - {0.5f, i * 0.5f, 0.5f, -i * 0.5f}, - {-i * 0.5f, 0.5f, i * 0.5f, 0.5f}}, - .flow_data = {"+XX", "+ZX", "+IX", "+YZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -H 1 -CNOT 1 0 -S 0 -H 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "YCY", - .id = GateType::YCY, - .best_candidate_inverse_id = GateType::YCY, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The Y-controlled Y gate. -First qubit is the control, second qubit is the target. - -Applies a Y gate to the target if the control is in the |-i> state. - -Negates the amplitude of the |-i>|-i> state. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = - {{0.5f, -i * 0.5f, -i * 0.5f, 0.5f}, - {i * 0.5f, 0.5f, -0.5f, -i * 0.5f}, - {i * 0.5f, -0.5f, 0.5f, -i * 0.5f}, - {0.5f, i * 0.5f, i * 0.5f, 0.5f}}, - .flow_data = {"+XY", "+ZY", "+YX", "+YZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -S 1 -S 1 -S 1 -H 0 -CNOT 0 1 -H 0 -S 0 -S 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "YCZ", - .id = GateType::YCZ, - .best_candidate_inverse_id = GateType::YCZ, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS | GATE_CAN_TARGET_BITS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The Y-controlled Z gate. -Applies a Z gate to the target if the control is in the |-i> state. -Equivalently: negates the amplitude of the |-i>|1> state. -Same as a CY gate, but with reversed qubit order. -The first qubit is called the control, and the second qubit is the target. - -To perform a classically controlled Y, replace the Z target with a `rec` -target like rec[-2]. - -To perform an I or Y gate as configured by sweep data, replace the -Z target with a `sweep` target like sweep[3]. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. - -Example: - - # Apply Y to qubit 5 controlled by qubit 2. - YCZ 5 2 - - # Perform CY 2 5 then CY 4 2. - YCZ 5 2 2 4 - - # Apply Y to qubit 6 if the most recent measurement result was TRUE. - YCZ 6 rec[-1] - - # Apply Y to qubits 7 and 8 conditioned on sweep configuration data. - YCZ 7 sweep[5] 8 sweep[5] -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 0, -i}, {0, 0, i, 0}}, - .flow_data = {"+XZ", "+ZZ", "+YX", "+IZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -CNOT 1 0 -S 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "CX", - .id = GateType::CX, - .best_candidate_inverse_id = GateType::CX, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS | GATE_CAN_TARGET_BITS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The Z-controlled X gate. -Applies an X gate to the target if the control is in the |1> state. -Equivalently: negates the amplitude of the |1>|-> state. -The first qubit is called the control, and the second qubit is the target. - -To perform a classically controlled X, replace the control with a `rec` -target like rec[-2]. - -To perform an I or X gate as configured by sweep data, replace the -control with a `sweep` target like sweep[3]. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. - -Example: - - # Bit flip qubit 5 controlled by qubit 2. - CX 2 5 - - # Perform CX 2 5 then CX 4 2. - CX 2 5 4 2 - - # Bit flip qubit 6 if the most recent measurement result was TRUE. - CX rec[-1] 6 - - # Bit flip qubits 7 and 8 conditioned on sweep configuration data. - CX sweep[5] 7 sweep[5] 8 -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 1, 0}, {0, 1, 0, 0}}, - .flow_data = {"+XX", "+ZI", "+IX", "+ZZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -CNOT 0 1 -)CIRCUIT", - }); - - add_gate_alias(failed, "ZCX", "CX"); - add_gate_alias(failed, "CNOT", "CX"); - - add_gate( - failed, - Gate{ - .name = "CY", - .id = GateType::CY, - .best_candidate_inverse_id = GateType::CY, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS | GATE_CAN_TARGET_BITS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The Z-controlled Y gate. -Applies a Y gate to the target if the control is in the |1> state. -Equivalently: negates the amplitude of the |1>|-i> state. -The first qubit is the control, and the second qubit is the target. - -To perform a classically controlled Y, replace the control with a `rec` -target like rec[-2]. - -To perform an I or Y gate as configured by sweep data, replace the -control with a `sweep` target like sweep[3]. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. - -Example: - - # Apply Y to qubit 5 controlled by qubit 2. - CY 2 5 - - # Perform CY 2 5 then CX 4 2. - CY 2 5 4 2 - - # Apply Y to qubit 6 if the most recent measurement result was TRUE. - CY rec[-1] 6 - - # Apply Y to qubits 7 and 8 conditioned on sweep configuration data. - CY sweep[5] 7 sweep[5] 8 -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, 0, 0, -i}, {0, 0, 1, 0}, {0, i, 0, 0}}, - .flow_data = {"+XY", "+ZI", "+ZX", "+ZZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 1 -S 1 -S 1 -CNOT 0 1 -S 1 -)CIRCUIT", - }); - - add_gate_alias(failed, "ZCY", "CY"); - - add_gate( - failed, - Gate{ - .name = "CZ", - .id = GateType::CZ, - .best_candidate_inverse_id = GateType::CZ, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS | GATE_CAN_TARGET_BITS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -The Z-controlled Z gate. -Applies a Z gate to the target if the control is in the |1> state. -Equivalently: negates the amplitude of the |1>|1> state. -The first qubit is called the control, and the second qubit is the target. - -To perform a classically controlled Z, replace either qubit with a `rec` -target like rec[-2]. - -To perform an I or Z gate as configured by sweep data, replace either qubit -with a `sweep` target like sweep[3]. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. - -Example: - - # Apply Z to qubit 5 controlled by qubit 2. - CZ 2 5 - - # Perform CZ 2 5 then CZ 4 2. - CZ 2 5 4 2 - - # Apply Z to qubit 6 if the most recent measurement result was TRUE. - CZ rec[-1] 6 - - # Apply Z to qubit 7 if the 3rd most recent measurement result was TRUE. - CZ 7 rec[-3] - - # Apply Z to qubits 7 and 8 conditioned on sweep configuration data. - CZ sweep[5] 7 8 sweep[5] -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, -1}}, - .flow_data = {"+XZ", "+ZI", "+ZX", "+IZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 1 -CNOT 0 1 -H 1 -)CIRCUIT", - }); - - add_gate_alias(failed, "ZCZ", "CZ"); -} diff --git a/src/stim/gates/gate_data_hada.cc b/src/stim/gates/gate_data_hada.cc deleted file mode 100644 index 419cc9b4d..000000000 --- a/src/stim/gates/gate_data_hada.cc +++ /dev/null @@ -1,114 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -static constexpr std::complex i = std::complex(0, 1); -static constexpr std::complex s = 0.7071067811865475244f; - -void GateDataMap::add_gate_data_hada(bool &failed) { - add_gate( - failed, - Gate{ - .name = "H", - .id = GateType::H, - .best_candidate_inverse_id = GateType::H, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -The Hadamard gate. -Swaps the X and Z axes. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{s, s}, {s, -s}}, - .flow_data = {"+Z", "+X"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -)CIRCUIT", - }); - - add_gate_alias(failed, "H_XZ", "H"); - - add_gate( - failed, - Gate{ - .name = "H_XY", - .id = GateType::H_XY, - .best_candidate_inverse_id = GateType::H_XY, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -A variant of the Hadamard gate that swaps the X and Y axes (instead of X and Z). - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0, s - i * s}, {s + i * s, 0}}, - .flow_data = {"+Y", "-Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -S 0 -S 0 -H 0 -S 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "H_YZ", - .id = GateType::H_YZ, - .best_candidate_inverse_id = GateType::H_YZ, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -A variant of the Hadamard gate that swaps the Y and Z axes (instead of X and Z). - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{s, -i * s}, {i * s, -s}}, - .flow_data = {"-X", "+Y"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -S 0 -H 0 -S 0 -S 0 -)CIRCUIT", - }); -} diff --git a/src/stim/gates/gate_data_heralded.cc b/src/stim/gates/gate_data_heralded.cc deleted file mode 100644 index 45515bb58..000000000 --- a/src/stim/gates/gate_data_heralded.cc +++ /dev/null @@ -1,183 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -void GateDataMap::add_gate_data_heralded(bool &failed) { - add_gate( - failed, - Gate{ - .name = "HERALDED_ERASE", - .id = GateType::HERALDED_ERASE, - .best_candidate_inverse_id = GateType::HERALDED_ERASE, - .arg_count = 1, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES | - GATE_PRODUCES_RESULTS), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -The heralded erasure noise channel. - -Whether or not this noise channel fires is recorded into the measurement -record. When it doesn't fire, nothing happens to the target qubit and a -0 is recorded. When it does fire, a 1 is recorded and the target qubit -is erased to the maximally mixed state by applying X_ERROR(0.5) and -Z_ERROR(0.5). - -CAUTION: when converting a circuit with this error into a detector -error model, this channel is split into multiple potential effects. -In the context of a DEM, these effects are considered independent. -This is an approximation, because independent effects can be combined. -The effect of this approximation, assuming a detector is declared -on the herald, is that it appears this detector can be cancelled out -by two of the (originally disjoint) heralded effects firing together. -Sampling from the DEM instead of the circuit can thus produce unheralded -errors, even if the circuit noise model only contains heralded errors. -These issues occur with probability p^2, where p is the probability of a -heralded error, since two effects that came from the same heralded error -must occur together to cancel out the herald detector. This also means -a decoder configured using the DEM will think there's a chance of unheralded -errors even if the circuit the DEM came from only uses heralded errors. - -Parens Arguments: - - A single float (p) specifying the chance of the noise firing. - -Targets: - - Qubits to apply single-qubit depolarizing noise to. Each target - is operated on independently. - -Pauli Mixture: - - 1-p: record 0, apply I - p/4: record 1, apply I - p/4: record 1, apply X - p/4: record 1, apply Y - p/4: record 1, apply Z - -Examples: - - # Erase qubit 0 with probability 1% - HERALDED_ERASE(0.01) 0 - # Declare a flag detector based on the erasure - DETECTOR rec[-1] - - # Erase qubit 2 with 2% probability - # Separately, erase qubit 3 with 2% probability - HERALDED_ERASE(0.02) 2 3 - - # Do an XXXX measurement - MPP X2*X3*X5*X7 - # Apply partially-heralded noise to the two qubits - HERALDED_ERASE(0.01) 2 3 5 7 - DEPOLARIZE1(0.0001) 2 3 5 7 - # Repeat the XXXX measurement - MPP X2*X3*X5*X7 - # Declare a detector comparing the two XXXX measurements - DETECTOR rec[-1] rec[-6] - # Declare flag detectors based on the erasures - DETECTOR rec[-2] - DETECTOR rec[-3] - DETECTOR rec[-4] - DETECTOR rec[-5] -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "HERALDED_PAULI_CHANNEL_1", - .id = GateType::HERALDED_PAULI_CHANNEL_1, - .best_candidate_inverse_id = GateType::HERALDED_PAULI_CHANNEL_1, - .arg_count = 4, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES | - GATE_PRODUCES_RESULTS), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -A heralded error channel that applies biased noise. - -This error records a bit into the measurement record, indicating whether -or not the herald fired. How likely it is that the herald fires, and the -corresponding chance of each possible error effect (I, X, Y, or Z) are -configured by the parens arguments of the instruction. - -CAUTION: when converting a circuit with this error into a detector -error model, this channel is split into multiple potential effects. -In the context of a DEM, these effects are considered independent. -This is an approximation, because independent effects can be combined. -The effect of this approximation, assuming a detector is declared -on the herald, is that it appears this detector can be cancelled out -by two of the (originally disjoint) heralded effects firing together. -Sampling from the DEM instead of the circuit can thus produce unheralded -errors, even if the circuit noise model only contains heralded errors. -These issues occur with probability p^2, where p is the probability of a -heralded error, since two effects that came from the same heralded error -must occur together to cancel out the herald detector. This also means -a decoder configured using the DEM will think there's a chance of unheralded -errors even if the circuit the DEM came from only uses heralded errors. - -Parens Arguments: - - This instruction takes four arguments (pi, px, py, pz). The - arguments are disjoint probabilities, specifying the chances - of heralding with various effects. - - pi is the chance of heralding with no effect (a false positive). - px is the chance of heralding with an X error. - py is the chance of heralding with a Y error. - pz is the chance of heralding with a Z error. - -Targets: - - Qubits to apply heralded biased noise to. - -Pauli Mixture: - - 1-pi-px-py-pz: record 0, apply I - pi: record 1, apply I - px: record 1, apply X - py: record 1, apply Y - pz: record 1, apply Z - -Examples: - - # With 10% probability perform a phase flip of qubit 0. - HERALDED_PAULI_CHANNEL_1(0, 0, 0, 0.1) 0 - DETECTOR rec[-1] # Include the herald in detectors available to the decoder - - # With 20% probability perform a heralded dephasing of qubit 0. - HERALDED_PAULI_CHANNEL_1(0.1, 0, 0, 0.1) 0 - DETECTOR rec[-1] - - # Subject a Bell Pair to heralded noise. - MXX 0 1 - MZZ 0 1 - HERALDED_PAULI_CHANNEL_1(0.01, 0.02, 0.03, 0.04) 0 1 - MXX 0 1 - MZZ 0 1 - DETECTOR rec[-1] rec[-5] # Did ZZ stabilizer change? - DETECTOR rec[-2] rec[-6] # Did XX stabilizer change? - DETECTOR rec[-3] # Did the herald on qubit 1 fire? - DETECTOR rec[-4] # Did the herald on qubit 0 fire? -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); -} diff --git a/src/stim/gates/gate_data_noisy.cc b/src/stim/gates/gate_data_noisy.cc deleted file mode 100644 index e58b370f4..000000000 --- a/src/stim/gates/gate_data_noisy.cc +++ /dev/null @@ -1,416 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -void GateDataMap::add_gate_data_noisy(bool &failed) { - add_gate( - failed, - Gate{ - .name = "DEPOLARIZE1", - .id = GateType::DEPOLARIZE1, - .best_candidate_inverse_id = GateType::DEPOLARIZE1, - .arg_count = 1, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -The single qubit depolarizing channel. - -Applies a single-qubit depolarizing error with the given probability. -When a single-qubit depolarizing error is applied, a random Pauli -error (except for I) is chosen and applied. Note that this means -maximal mixing occurs when the probability parameter is set to 75%, -rather than at 100%. - -Applies a randomly chosen Pauli with a given probability. - -Parens Arguments: - - A single float (p) specifying the depolarization strength. - -Targets: - - Qubits to apply single-qubit depolarizing noise to. - -Pauli Mixture: - - 1-p: I - p/3: X - p/3: Y - p/3: Z - -Examples: - - # Apply 1-qubit depolarization to qubit 0 using p=1% - DEPOLARIZE2(0.01) 0 - - # Apply 1-qubit depolarization to qubit 2 - # Separately apply 1-qubit depolarization to qubits 3 and 5 - DEPOLARIZE1(0.01) 2 3 5 - - # Maximally mix qubits 0 through 2 - DEPOLARIZE1(0.75) 0 1 2 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "DEPOLARIZE2", - .id = GateType::DEPOLARIZE2, - .best_candidate_inverse_id = GateType::DEPOLARIZE2, - .arg_count = 1, - .flags = (GateFlags)(GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES | GATE_TARGETS_PAIRS), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -The two qubit depolarizing channel. - -Applies a two-qubit depolarizing error with the given probability. -When a two-qubit depolarizing error is applied, a random pair of Pauli -errors (except for II) is chosen and applied. Note that this means -maximal mixing occurs when the probability parameter is set to 93.75%, -rather than at 100%. - -Parens Arguments: - - A single float (p) specifying the depolarization strength. - -Targets: - - Qubit pairs to apply two-qubit depolarizing noise to. - -Pauli Mixture: - - 1-p: II - p/15: IX - p/15: IY - p/15: IZ - p/15: XI - p/15: XX - p/15: XY - p/15: XZ - p/15: YI - p/15: YX - p/15: YY - p/15: YZ - p/15: ZI - p/15: ZX - p/15: ZY - p/15: ZZ - -Examples: - - # Apply 2-qubit depolarization to qubit 0 and qubit 1 using p=1% - DEPOLARIZE2(0.01) 0 1 - - # Apply 2-qubit depolarization to qubit 2 and qubit 3 - # Separately apply 2-qubit depolarization to qubit 5 and qubit 7 - DEPOLARIZE2(0.01) 2 3 5 7 - - # Maximally mix qubits 0 through 3 - DEPOLARIZE2(0.9375) 0 1 2 3 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "X_ERROR", - .id = GateType::X_ERROR, - .best_candidate_inverse_id = GateType::X_ERROR, - .arg_count = 1, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -Applies a Pauli X with a given probability. - -Parens Arguments: - - A single float specifying the probability of applying an X operation. - -Targets: - - Qubits to apply bit flip noise to. - -Pauli Mixture: - - 1-p: I - p : X -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "Y_ERROR", - .id = GateType::Y_ERROR, - .best_candidate_inverse_id = GateType::Y_ERROR, - .arg_count = 1, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -Applies a Pauli Y with a given probability. - -Parens Arguments: - - A single float specifying the probability of applying a Y operation. - -Targets: - - Qubits to apply Y flip noise to. - -Pauli Mixture: - - 1-p: I - p : Y -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "Z_ERROR", - .id = GateType::Z_ERROR, - .best_candidate_inverse_id = GateType::Z_ERROR, - .arg_count = 1, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -Applies a Pauli Z with a given probability. - -Parens Arguments: - - A single float specifying the probability of applying a Z operation. - -Targets: - - Qubits to apply phase flip noise to. - -Pauli Mixture: - - 1-p: I - p : Z -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "PAULI_CHANNEL_1", - .id = GateType::PAULI_CHANNEL_1, - .best_candidate_inverse_id = GateType::PAULI_CHANNEL_1, - .arg_count = 3, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -A single qubit Pauli error channel with explicitly specified probabilities for each case. - -Parens Arguments: - - Three floats specifying disjoint Pauli case probabilities. - px: Disjoint probability of applying an X error. - py: Disjoint probability of applying a Y error. - pz: Disjoint probability of applying a Z error. - -Targets: - - Qubits to apply the custom noise channel to. - -Example: - - # Sample errors from the distribution 10% X, 15% Y, 20% Z, 55% I. - # Apply independently to qubits 1, 2, 4. - PAULI_CHANNEL_1(0.1, 0.15, 0.2) 1 2 4 - -Pauli Mixture: - - 1-px-py-pz: I - px: X - py: Y - pz: Z -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "PAULI_CHANNEL_2", - .id = GateType::PAULI_CHANNEL_2, - .best_candidate_inverse_id = GateType::PAULI_CHANNEL_2, - .arg_count = 15, - .flags = (GateFlags)(GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES | GATE_TARGETS_PAIRS), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -A two qubit Pauli error channel with explicitly specified probabilities for each case. - -Parens Arguments: - - Fifteen floats specifying the disjoint probabilities of each possible Pauli pair - that can occur (except for the non-error double identity case). - The disjoint probability arguments are (in order): - - 1. pix: Probability of applying an IX operation. - 2. piy: Probability of applying an IY operation. - 3. piz: Probability of applying an IZ operation. - 4. pxi: Probability of applying an XI operation. - 5. pxx: Probability of applying an XX operation. - 6. pxy: Probability of applying an XY operation. - 7. pxz: Probability of applying an XZ operation. - 8. pyi: Probability of applying a YI operation. - 9. pyx: Probability of applying a YX operation. - 10. pyy: Probability of applying a YY operation. - 11. pyz: Probability of applying a YZ operation. - 12. pzi: Probability of applying a ZI operation. - 13. pzx: Probability of applying a ZX operation. - 14. pzy: Probability of applying a ZY operation. - 15. pzz: Probability of applying a ZZ operation. - -Targets: - - Pairs of qubits to apply the custom noise channel to. - There must be an even number of targets. - -Example: - - # Sample errors from the distribution 10% XX, 20% YZ, 70% II. - # Apply independently to qubit pairs (1,2), (5,6), and (8,3) - PAULI_CHANNEL_2(0,0,0, 0.1,0,0,0, 0,0,0,0.2, 0,0,0,0) 1 2 5 6 8 3 - -Pauli Mixture: - - 1-pix-piy-piz-pxi-pxx-pxy-pxz-pyi-pyx-pyy-pyz-pzi-pzx-pzy-pzz: II - pix: IX - piy: IY - piz: IZ - pxi: XI - pxx: XX - pxy: XY - pxz: XZ - pyi: YI - pyx: YX - pyy: YY - pyz: YZ - pzi: ZI - pzx: ZX - pzy: ZY - pzz: ZZ -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - - add_gate( - failed, - Gate{ - .name = "E", - .id = GateType::E, - .best_candidate_inverse_id = GateType::E, - .arg_count = 1, - .flags = (GateFlags)(GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES | GATE_TARGETS_PAULI_STRING | - GATE_IS_NOT_FUSABLE), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -Probabilistically applies a Pauli product error with a given probability. -Sets the "correlated error occurred flag" to true if the error occurred. -Otherwise sets the flag to false. - -See also: `ELSE_CORRELATED_ERROR`. - -Parens Arguments: - - A single float specifying the probability of applying the Paulis making up the error. - -Targets: - - Pauli targets specifying the Paulis to apply when the error occurs. - Note that, for backwards compatibility reasons, the targets are not combined using combiners (`*`). - They are implicitly all combined. - -Example: - - # With 60% probability, uniformly pick X1*Y2 or Z2*Z3 or X1*Y2*Z3. - CORRELATED_ERROR(0.2) X1 Y2 - ELSE_CORRELATED_ERROR(0.25) Z2 Z3 - ELSE_CORRELATED_ERROR(0.33333333333) X1 Y2 Z3 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); - add_gate_alias(failed, "CORRELATED_ERROR", "E"); - add_gate( - failed, - Gate{ - .name = "ELSE_CORRELATED_ERROR", - .id = GateType::ELSE_CORRELATED_ERROR, - .best_candidate_inverse_id = GateType::ELSE_CORRELATED_ERROR, - .arg_count = 1, - .flags = (GateFlags)(GATE_IS_NOISY | GATE_ARGS_ARE_DISJOINT_PROBABILITIES | GATE_TARGETS_PAULI_STRING | - GATE_IS_NOT_FUSABLE), - .category = "F_Noise Channels", - .help = R"MARKDOWN( -Probabilistically applies a Pauli product error with a given probability, unless the "correlated error occurred flag" is set. -If the error occurs, sets the "correlated error occurred flag" to true. -Otherwise leaves the flag alone. - -Note: when converting a circuit into a detector error model, every `ELSE_CORRELATED_ERROR` instruction must be preceded by -an ELSE_CORRELATED_ERROR instruction or an E instruction. In other words, ELSE_CORRELATED_ERROR instructions should appear -in contiguous chunks started by a CORRELATED_ERROR. - -See also: `CORRELATED_ERROR`. - -Parens Arguments: - - A single float specifying the probability of applying the Paulis making up the error, conditioned on the "correlated - error occurred flag" being False. - -Targets: - - Pauli targets specifying the Paulis to apply when the error occurs. - Note that, for backwards compatibility reasons, the targets are not combined using combiners (`*`). - They are implicitly all combined. - -Example: - - # With 60% probability, uniformly pick X1*Y2 or Z2*Z3 or X1*Y2*Z3. - CORRELATED_ERROR(0.2) X1 Y2 - ELSE_CORRELATED_ERROR(0.25) Z2 Z3 - ELSE_CORRELATED_ERROR(0.33333333333) X1 Y2 Z3 -)MARKDOWN", - .unitary_data = {}, - .flow_data = {}, - .h_s_cx_m_r_decomposition = nullptr, - }); -} diff --git a/src/stim/gates/gate_data_pair_measure.cc b/src/stim/gates/gate_data_pair_measure.cc deleted file mode 100644 index 55472c2a7..000000000 --- a/src/stim/gates/gate_data_pair_measure.cc +++ /dev/null @@ -1,230 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -void GateDataMap::add_gate_data_pair_measure(bool &failed) { - add_gate( - failed, - Gate{ - .name = "MXX", - .id = GateType::MXX, - .best_candidate_inverse_id = GateType::MXX, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_TARGETS_PAIRS | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "L_Pair Measurement Gates", - .help = R"MARKDOWN( -Two-qubit X basis parity measurement. - -This operation measures whether pairs of qubits are in the {|++>,|-->} subspace or in the -{|+->,|-+>} subspace of the two qubit state space. |+> and |-> are the +1 and -1 -eigenvectors of the X operator. - -If the qubits were in the {|++>,|-->} subspace, False is appended to the measurement record. -If the qubits were in the {|+->,|-+>} subspace, True is appended to the measurement record. -Inverting one of the qubit targets inverts the result. - -Parens Arguments: - - If no parens argument is given, the measurement is perfect. - If one parens argument is given, the measurement result is noisy. - The argument is the probability of returning the wrong result. - -Targets: - - The pairs of qubits to measure in the X basis. - - This operation accepts inverted qubit targets (like `!5` instead of `5`). Inverted - targets flip the measurement result. - -Examples: - - # Measure the +XX observable of qubit 1 vs qubit 2. - MXX 1 2 - - # Measure the -XX observable of qubit 1 vs qubit 2. - MXX !1 2 - - # Do a noisy measurement of the +XX observable of qubit 2 vs qubit 3. - # The result recorded to the measurement record will be flipped 1% of the time. - MXX(0.01) 2 3 - - # Measure the +XX observable qubit 1 vs qubit 2, and also qubit 8 vs qubit 9 - MXX 1 2 8 9 - - # Perform multiple noisy measurements. - # Each measurement has an independent 2% chance of being recorded wrong. - MXX(0.02) 2 3 5 7 11 19 17 4 -)MARKDOWN", - .unitary_data = {}, - .flow_data = - { - "X_ -> +X_", - "_X -> +_X", - "ZZ -> +ZZ", - "XX -> rec[-1]", - }, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -CX 0 1 -H 0 -M 0 -H 0 -CX 0 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "MYY", - .id = GateType::MYY, - .best_candidate_inverse_id = GateType::MYY, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_TARGETS_PAIRS | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "L_Pair Measurement Gates", - .help = R"MARKDOWN( -Two-qubit Y basis parity measurement. - -This operation measures whether pairs of qubits are in the {|ii>,|jj>} subspace or in the -{|ij>,|ji>} subspace of the two qubit state space. |i> and |j> are the +1 and -1 -eigenvectors of the Y operator. - -If the qubits were in the {|ii>,|jj>} subspace, False is appended to the measurement record. -If the qubits were in the {|ij>,|ji>} subspace, True is appended to the measurement record. -Inverting one of the qubit targets inverts the result. - -Parens Arguments: - - If no parens argument is given, the measurement is perfect. - If one parens argument is given, the measurement result is noisy. - The argument is the probability of returning the wrong result. - -Targets: - - The pairs of qubits to measure in the Y basis. - - This operation accepts inverted qubit targets (like `!5` instead of `5`). Inverted - targets flip the measurement result. - -Examples: - - # Measure the +YY observable of qubit 1 vs qubit 2. - MYY 1 2 - - # Measure the -YY observable of qubit 1 vs qubit 2. - MYY !1 2 - - # Do a noisy measurement of the +YY observable of qubit 2 vs qubit 3. - # The result recorded to the measurement record will be flipped 1% of the time. - MYY(0.01) 2 3 - - # Measure the +YY observable qubit 1 vs qubit 2, and also qubit 8 vs qubit 9 - MYY 1 2 8 9 - - # Perform multiple noisy measurements. - # Each measurement has an independent 2% chance of being recorded wrong. - MYY(0.02) 2 3 5 7 11 19 17 4 -)MARKDOWN", - .unitary_data = {}, - .flow_data = - { - "XX -> +XX", - "Y_ -> +Y_", - "_Y -> +_Y", - "YY -> rec[-1]", - }, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 1 -CX 0 1 -H 0 -M 0 -S 1 1 -H 0 -CX 0 1 -S 0 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "MZZ", - .id = GateType::MZZ, - .best_candidate_inverse_id = GateType::MZZ, - .arg_count = ARG_COUNT_SYGIL_ZERO_OR_ONE, - .flags = (GateFlags)(GATE_TARGETS_PAIRS | GATE_PRODUCES_RESULTS | GATE_IS_NOISY | - GATE_ARGS_ARE_DISJOINT_PROBABILITIES), - .category = "L_Pair Measurement Gates", - .help = R"MARKDOWN( -Two-qubit Z basis parity measurement. - -This operation measures whether pairs of qubits are in the {|00>,|11>} subspace or in the -{|01>,|10>} subspace of the two qubit state space. |0> and |1> are the +1 and -1 -eigenvectors of the Z operator. - -If the qubits were in the {|00>,|11>} subspace, False is appended to the measurement record. -If the qubits were in the {|01>,|10>} subspace, True is appended to the measurement record. -Inverting one of the qubit targets inverts the result. - -Parens Arguments: - - If no parens argument is given, the measurement is perfect. - If one parens argument is given, the measurement result is noisy. - The argument is the probability of returning the wrong result. - -Targets: - - The pairs of qubits to measure in the Z basis. - - This operation accepts inverted qubit targets (like `!5` instead of `5`). Inverted - targets flip the measurement result. - -Examples: - - # Measure the +ZZ observable of qubit 1 vs qubit 2. - MZZ 1 2 - - # Measure the -ZZ observable of qubit 1 vs qubit 2. - MZZ !1 2 - - # Do a noisy measurement of the +ZZ observable of qubit 2 vs qubit 3. - # The result recorded to the measurement record will be flipped 1% of the time. - MZZ(0.01) 2 3 - - # Measure the +ZZ observable qubit 1 vs qubit 2, and also qubit 8 vs qubit 9 - MZZ 1 2 8 9 - - # Perform multiple noisy measurements. - # Each measurement has an independent 2% chance of being recorded wrong. - MZZ(0.02) 2 3 5 7 11 19 17 4 -)MARKDOWN", - .unitary_data = {}, - .flow_data = - { - "XX -> XX", - "Z_ -> +Z_", - "_Z -> +_Z", - "ZZ -> rec[-1]", - }, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -CX 0 1 -M 1 -CX 0 1 -)CIRCUIT", - }); -} diff --git a/src/stim/gates/gate_data_pauli.cc b/src/stim/gates/gate_data_pauli.cc deleted file mode 100644 index a00bdb739..000000000 --- a/src/stim/gates/gate_data_pauli.cc +++ /dev/null @@ -1,141 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -static constexpr std::complex i = std::complex(0, 1); - -void GateDataMap::add_gate_data_pauli(bool &failed) { - add_gate( - failed, - Gate{ - .name = "I", - .id = GateType::I, - .best_candidate_inverse_id = GateType::I, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "A_Pauli Gates", - .help = R"MARKDOWN( -The identity gate. -Does nothing to the target qubits. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to do nothing to. -)MARKDOWN", - .unitary_data = {{1, 0}, {0, 1}}, - .flow_data = {"+X", "+Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -# (no operations) -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "X", - .id = GateType::X, - .best_candidate_inverse_id = GateType::X, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "A_Pauli Gates", - .help = R"MARKDOWN( -The Pauli X gate. -The bit flip gate. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0, 1}, {1, 0}}, - .flow_data = {"+X", "-Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -S 0 -S 0 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "Y", - .id = GateType::Y, - .best_candidate_inverse_id = GateType::Y, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "A_Pauli Gates", - .help = R"MARKDOWN( -The Pauli Y gate. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0, -i}, {i, 0}}, - .flow_data = {"-X", "-Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -H 0 -S 0 -S 0 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "Z", - .id = GateType::Z, - .best_candidate_inverse_id = GateType::Z, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "A_Pauli Gates", - .help = R"MARKDOWN( -The Pauli Z gate. -The phase flip gate. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{1, 0}, {0, -1}}, - .flow_data = {"-X", "+Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -)CIRCUIT", - }); -} diff --git a/src/stim/gates/gate_data_period_3.cc b/src/stim/gates/gate_data_period_3.cc deleted file mode 100644 index fc77b4668..000000000 --- a/src/stim/gates/gate_data_period_3.cc +++ /dev/null @@ -1,79 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -static constexpr std::complex i = std::complex(0, 1); - -void GateDataMap::add_gate_data_period_3(bool &failed) { - add_gate( - failed, - Gate{ - .name = "C_XYZ", - .id = GateType::C_XYZ, - .best_candidate_inverse_id = GateType::C_ZYX, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -Right handed period 3 axis cycling gate, sending X -> Y -> Z -> X. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0.5f - i * 0.5f, -0.5f - 0.5f * i}, {0.5f - 0.5f * i, 0.5f + 0.5f * i}}, - .flow_data = {"Y", "X"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "C_ZYX", - .id = GateType::C_ZYX, - .best_candidate_inverse_id = GateType::C_XYZ, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -Left handed period 3 axis cycling gate, sending Z -> Y -> X -> Z. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0.5f + i * 0.5f, 0.5f + 0.5f * i}, {-0.5f + 0.5f * i, 0.5f - 0.5f * i}}, - .flow_data = {"Z", "Y"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -S 0 -)CIRCUIT", - }); -} diff --git a/src/stim/gates/gate_data_period_4.cc b/src/stim/gates/gate_data_period_4.cc deleted file mode 100644 index 585246688..000000000 --- a/src/stim/gates/gate_data_period_4.cc +++ /dev/null @@ -1,203 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -static constexpr std::complex i = std::complex(0, 1); - -void GateDataMap::add_gate_data_period_4(bool &failed) { - add_gate( - failed, - Gate{ - .name = "SQRT_X", - .id = GateType::SQRT_X, - .best_candidate_inverse_id = GateType::SQRT_X_DAG, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -Principal square root of X gate. -Phases the amplitude of |-> by i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0.5f + 0.5f * i, 0.5f - 0.5f * i}, {0.5f - 0.5f * i, 0.5f + 0.5f * i}}, - .flow_data = {"+X", "-Y"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -S 0 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "SQRT_X_DAG", - .id = GateType::SQRT_X_DAG, - .best_candidate_inverse_id = GateType::SQRT_X, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -Adjoint of the principal square root of X gate. -Phases the amplitude of |-> by -i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0.5f - 0.5f * i, 0.5f + 0.5f * i}, {0.5f + 0.5f * i, 0.5f - 0.5f * i}}, - .flow_data = {"+X", "+Y"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -H 0 -S 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "SQRT_Y", - .id = GateType::SQRT_Y, - .best_candidate_inverse_id = GateType::SQRT_Y_DAG, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -Principal square root of Y gate. -Phases the amplitude of |-i> by i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0.5f + 0.5f * i, -0.5f - 0.5f * i}, {0.5f + 0.5f * i, 0.5f + 0.5f * i}}, - .flow_data = {"-Z", "+X"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "SQRT_Y_DAG", - .id = GateType::SQRT_Y_DAG, - .best_candidate_inverse_id = GateType::SQRT_Y, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -Adjoint of the principal square root of Y gate. -Phases the amplitude of |-i> by -i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{0.5f - 0.5f * i, 0.5f - 0.5f * i}, {-0.5f + 0.5f * i, 0.5f - 0.5f * i}}, - .flow_data = {"+Z", "-X"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -S 0 -S 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "S", - .id = GateType::S, - .best_candidate_inverse_id = GateType::S_DAG, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -Principal square root of Z gate. -Phases the amplitude of |1> by i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{1, 0}, {0, i}}, - .flow_data = {"+Y", "+Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -)CIRCUIT", - }); - - add_gate_alias(failed, "SQRT_Z", "S"); - - add_gate( - failed, - Gate{ - .name = "S_DAG", - .id = GateType::S_DAG, - .best_candidate_inverse_id = GateType::S, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_SINGLE_QUBIT_GATE | GATE_IS_UNITARY), - .category = "B_Single Qubit Clifford Gates", - .help = R"MARKDOWN( -Adjoint of the principal square root of Z gate. -Phases the amplitude of |1> by -i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubits to operate on. -)MARKDOWN", - .unitary_data = {{1, 0}, {0, -i}}, - .flow_data = {"-Y", "+Z"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -)CIRCUIT", - }); - - add_gate_alias(failed, "SQRT_Z_DAG", "S_DAG"); -} diff --git a/src/stim/gates/gate_data_pp.cc b/src/stim/gates/gate_data_pp.cc deleted file mode 100644 index cab1c9935..000000000 --- a/src/stim/gates/gate_data_pp.cc +++ /dev/null @@ -1,254 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -static constexpr std::complex i = std::complex(0, 1); - -void GateDataMap::add_gate_data_pp(bool &failed) { - add_gate( - failed, - Gate{ - .name = "SQRT_XX", - .id = GateType::SQRT_XX, - .best_candidate_inverse_id = GateType::SQRT_XX_DAG, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Phases the -1 eigenspace of the XX observable by i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = - {{0.5f + 0.5f * i, 0, 0, 0.5f - 0.5f * i}, - {0, 0.5f + 0.5f * i, 0.5f - 0.5f * i, 0}, - {0, 0.5f - 0.5f * i, 0.5f + 0.5f * i, 0}, - {0.5f - 0.5f * i, 0, 0, 0.5f + 0.5f * i}}, - .flow_data = {"+XI", "-YX", "+IX", "-XY"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -CNOT 0 1 -H 1 -S 0 -S 1 -H 0 -H 1 -)CIRCUIT", - }); - add_gate( - failed, - Gate{ - .name = "SQRT_XX_DAG", - .id = GateType::SQRT_XX_DAG, - .best_candidate_inverse_id = GateType::SQRT_XX, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Phases the -1 eigenspace of the XX observable by -i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = - {{0.5f - 0.5f * i, 0, 0, 0.5f + 0.5f * i}, - {0, 0.5f - 0.5f * i, 0.5f + 0.5f * i, 0}, - {0, 0.5f + 0.5f * i, 0.5f - 0.5f * i, 0}, - {0.5f + 0.5f * i, 0, 0, 0.5f - 0.5f * i}}, - .flow_data = {"+XI", "+YX", "+IX", "+XY"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -CNOT 0 1 -H 1 -S 0 -S 0 -S 0 -S 1 -S 1 -S 1 -H 0 -H 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "SQRT_YY", - .id = GateType::SQRT_YY, - .best_candidate_inverse_id = GateType::SQRT_YY_DAG, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Phases the -1 eigenspace of the YY observable by i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = - {{0.5f + 0.5f * i, 0, 0, -0.5f + 0.5f * i}, - {0, 0.5f + 0.5f * i, 0.5f - 0.5f * i, 0}, - {0, 0.5f - 0.5f * i, 0.5f + 0.5f * i, 0}, - {-0.5f + 0.5f * i, 0, 0, 0.5f + 0.5f * i}}, - .flow_data = {"-ZY", "+XY", "-YZ", "+YX"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -S 1 -S 1 -S 1 -H 0 -CNOT 0 1 -H 1 -S 0 -S 1 -H 0 -H 1 -S 0 -S 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "SQRT_YY_DAG", - .id = GateType::SQRT_YY_DAG, - .best_candidate_inverse_id = GateType::SQRT_YY, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Phases the -1 eigenspace of the YY observable by -i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = - {{0.5f - 0.5f * i, 0, 0, -0.5f - 0.5f * i}, - {0, 0.5f - 0.5f * i, 0.5f + 0.5f * i, 0}, - {0, 0.5f + 0.5f * i, 0.5f - 0.5f * i, 0}, - {-0.5f - 0.5f * i, 0, 0, 0.5f - 0.5f * i}}, - .flow_data = {"+ZY", "-XY", "+YZ", "-YX"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -S 1 -H 0 -CNOT 0 1 -H 1 -S 0 -S 1 -H 0 -H 1 -S 0 -S 1 -S 1 -S 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "SQRT_ZZ", - .id = GateType::SQRT_ZZ, - .best_candidate_inverse_id = GateType::SQRT_ZZ_DAG, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Phases the -1 eigenspace of the ZZ observable by i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, i, 0, 0}, {0, 0, i, 0}, {0, 0, 0, 1}}, - .flow_data = {"+YZ", "+ZI", "+ZY", "+IZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 1 -CNOT 0 1 -H 1 -S 0 -S 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "SQRT_ZZ_DAG", - .id = GateType::SQRT_ZZ_DAG, - .best_candidate_inverse_id = GateType::SQRT_ZZ, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Phases the -1 eigenspace of the ZZ observable by -i. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, -i, 0, 0}, {0, 0, -i, 0}, {0, 0, 0, 1}}, - .flow_data = {"-YZ", "+ZI", "-ZY", "+IZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 1 -CNOT 0 1 -H 1 -S 0 -S 0 -S 0 -S 1 -S 1 -S 1 -)CIRCUIT", - }); -} diff --git a/src/stim/gates/gate_data_swaps.cc b/src/stim/gates/gate_data_swaps.cc deleted file mode 100644 index 5a47a811a..000000000 --- a/src/stim/gates/gate_data_swaps.cc +++ /dev/null @@ -1,210 +0,0 @@ -// 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/gates/gates.h" - -using namespace stim; - -static constexpr std::complex i = std::complex(0, 1); - -void GateDataMap::add_gate_data_swaps(bool &failed) { - add_gate( - failed, - Gate{ - .name = "SWAP", - .id = GateType::SWAP, - .best_candidate_inverse_id = GateType::SWAP, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Swaps two qubits. - -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 = {"+IX", "+IZ", "+XI", "+ZI"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -CNOT 0 1 -CNOT 1 0 -CNOT 0 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "ISWAP", - .id = GateType::ISWAP, - .best_candidate_inverse_id = GateType::ISWAP_DAG, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Swaps two qubits and phases the -1 eigenspace of the ZZ observable by i. -Equivalent to `SWAP` then `CZ` then `S` on both targets. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, 0, i, 0}, {0, i, 0, 0}, {0, 0, 0, 1}}, - .flow_data = {"+ZY", "+IZ", "+YZ", "+ZI"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -H 0 -CNOT 0 1 -CNOT 1 0 -H 1 -S 1 -S 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "ISWAP_DAG", - .id = GateType::ISWAP_DAG, - .best_candidate_inverse_id = GateType::ISWAP, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -Swaps two qubits and phases the -1 eigenspace of the ZZ observable by -i. -Equivalent to `SWAP` then `CZ` then `S_DAG` on both targets. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, 0, -i, 0}, {0, -i, 0, 0}, {0, 0, 0, 1}}, - .flow_data = {"-ZY", "+IZ", "-YZ", "+ZI"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -S 0 -S 0 -S 0 -S 1 -S 1 -S 1 -H 1 -CNOT 1 0 -CNOT 0 1 -H 0 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "CXSWAP", - .id = GateType::CXSWAP, - .best_candidate_inverse_id = GateType::SWAPCX, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -A combination CX-then-SWAP gate. -This gate is kak-equivalent to the iswap gate, but preserves X/Z noise bias. - -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, 0, 0, 1}, {0, 1, 0, 0}}, - .flow_data = {"+XX", "+IZ", "+XI", "+ZZ"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -CNOT 1 0 -CNOT 0 1 -)CIRCUIT", - }); - - add_gate( - failed, - Gate{ - .name = "SWAPCX", - .id = GateType::SWAPCX, - .best_candidate_inverse_id = GateType::CXSWAP, - .arg_count = 0, - .flags = (GateFlags)(GATE_IS_UNITARY | GATE_TARGETS_PAIRS), - .category = "C_Two Qubit Clifford Gates", - .help = R"MARKDOWN( -A combination SWAP-then-CX gate. -This gate is kak-equivalent to the iswap gate, but preserves X/Z noise bias. - -Parens Arguments: - - This instruction takes no parens arguments. - -Targets: - - Qubit pairs to operate on. -)MARKDOWN", - .unitary_data = {{1, 0, 0, 0}, {0, 0, 0, 1}, {0, 1, 0, 0}, {0, 0, 1, 0}}, - .flow_data = {"+IX", "+ZZ", "+XX", "+ZI"}, - .h_s_cx_m_r_decomposition = R"CIRCUIT( -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"); -} diff --git a/src/stim/gates/gates.cc b/src/stim/gates/gates.cc index b2ee94bf0..3b108cde9 100644 --- a/src/stim/gates/gates.cc +++ b/src/stim/gates/gates.cc @@ -17,31 +17,7 @@ using namespace stim; GateDataMap::GateDataMap() { - bool failed = false; items[0].name = "NOT_A_GATE"; - -// add_gate_data_annotations(failed); -// add_gate_data_blocks(failed); -// add_gate_data_collapsing(failed); -// add_gate_data_controlled(failed); -// add_gate_data_hada(failed); -// add_gate_data_heralded(failed); -// add_gate_data_noisy(failed); -// add_gate_data_pauli(failed); -// add_gate_data_period_3(failed); -// add_gate_data_period_4(failed); -// add_gate_data_pp(failed); -// add_gate_data_swaps(failed); -// add_gate_data_pair_measure(failed); -// for (size_t k = 1; k < NUM_DEFINED_GATES; k++) { -// if (items[k].name == nullptr) { -// std::cerr << "Uninitialized gate id: " << k << ".\n"; -// failed = true; -// } -// } -// if (failed) { -// throw std::out_of_range("Failed to initialize gate data."); -// } } void GateDataMap::add_gate(bool &failed, const Gate &gate) { diff --git a/src/stim/gates/gates.h b/src/stim/gates/gates.h index 0edd527a9..9d4249d8f 100644 --- a/src/stim/gates/gates.h +++ b/src/stim/gates/gates.h @@ -278,26 +278,6 @@ struct Gate { return out; } - std::vector>> unitary() const; - - /// Converts a single qubit unitary gate into an euler-angles rotation. - /// - /// Returns: - /// {theta, phi, lambda} using the same convention as qiskit. - /// Each angle is in radians. - /// For stabilizer operations, every angle will be a multiple of pi/2. - /// - /// The unitary matrix U of the operation can be recovered (up to global phase) - /// by computing U = RotZ(phi) * RotY(theta) * RotZ(lambda). - std::array to_euler_angles() const; - - /// Converts a single qubit unitary gate into an axis-angle rotation. - /// - /// Returns: - /// An array {x, y, z, a}. - /// is a unit vector indicating the axis of rotation. - /// is the angle of rotation in radians. - std::array to_axis_angle() const; }; inline bool _case_insensitive_mismatch(const char *text, size_t text_len, const char *bucket_name, uint8_t bucket_len) { @@ -321,19 +301,6 @@ struct GateDataMap { private: void add_gate(bool &failed, const Gate &data); void add_gate_alias(bool &failed, const char *alt_name, const char *canon_name); - void add_gate_data_annotations(bool &failed); - void add_gate_data_blocks(bool &failed); - void add_gate_data_heralded(bool &failed); - void add_gate_data_collapsing(bool &failed); - void add_gate_data_controlled(bool &failed); - void add_gate_data_hada(bool &failed); - void add_gate_data_noisy(bool &failed); - void add_gate_data_pauli(bool &failed); - void add_gate_data_period_3(bool &failed); - void add_gate_data_period_4(bool &failed); - void add_gate_data_pp(bool &failed); - void add_gate_data_swaps(bool &failed); - void add_gate_data_pair_measure(bool &failed); public: std::array hashed_name_to_gate_type_table;