-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: remove the uniqueness constraint on measurement keys #4274
Comments
I had imagined that reusing the same key with instances with different |
Classical control flow (#3232 and #3234) will add more complexity here. I was going through the
We may be able to get around this by some special casing but it won't be very clean. |
Should this also update i.e. if user appends a measurement on q1 and then a measurement on q2 both to the same key, they probably intended for the q2 measurement to happen after q1. Would we want to allow multiple distinct measurement ops with the same key within a single moment? (If we treat keys like qubits then the answer here is no. Which seems fine because you can just use a regular multi-qubit measurement op if that's what you want) |
Also, rather than storing a whole extra dimension, would a This would be strictly less powerful than storing the entire array, but it would also be a less invasive change, and wouldn't change the output dataframe types at all. Would it cover the real-world use cases? |
I think this is an central question to answer. We can allow this if ordering of ops within a moment is preserved, because otherwise when interpreting results one wouldn't be able to tell which bits came from which measurements in a moment. I think the order is preserved in the current implementation of Re: measurement op, this is an interesting idea, but would not cover the use cases I have in mind since we need to preserve all the data. But It's something we could potentially do in the future. |
I think I'd like to give this a shot. I think we can do it in a way that's still compatible with the existing measurement key paths.
I feel like this could be a nice addition, and would meld well with #4884 and #3266 to augment our classical logic capabilities. |
This would definitely make interop between stim and cirq a lot easier. |
This converts cirq.Result into an abstract base class which defines the interface provided by measurement result objects. We introduce a new class cirq.ResultDict which is the default implementation of this result type, based on a dict mapping string keys to array data. This will allow us to provide alternate implementations as needed, for example a result type that is based on a DataFrame and only converts to measurement dict on demand (cf #4774), or a result type that is based on experimental data (such as raw IQ data) and allows accessing this raw data while also converting to the standard measurements dict on demand (see #3868 for other possible Result implementations). Making this separation will also simplify the implementation of repeated measurement keys (#4274), since it will allow us to define the new interface for accessing data from repeated keys separately from the implementation of how this data is stored. Review: @95-martin-orion
Thanks to @95-martin-orion, we now have an official RFC for this proposal. |
Adds a `ClassicalDataStore` class so we can keep track of which qubits are associated to which measurements. Closes #3232. Initially this was created as part 14 (of 14) of https://tinyurl.com/cirq-feedforward to enable qudits in classical conditions, by storing and using dimensions of the measured qubits when calculating the integer value of each measurement when resolving sympy expressions. However it may have broader applicability. This approach also sets us up to more easily add different types of measurements (#3233, #4274). It will also ease the path to #3002 and #4449., as we can eventually pass this into `Result` rather than the raw `log_of_measurement_results` dictionary. (The return type of `_run` will have to be changed to `Sequence[C;assicalDataStoreReader]`. Related: #887, #3231 (open question @95-martin-orion whether this closes those or not) This PR contains a `ClassicalDataStoreReader` and `ClassicalDataStoreBase` parent "interface" for the `ClassicalDataStore` class as well. This will allow us to swap in different representations that may have different performance characteristics. See #3808 for an example use case. This could be done by adding an optional `ClassicalDataStore` factory method argument to the `SimulatorBase` initializer, or separately to sampler classes. (Note this is an alternative to #4778 for supporting qudits in sympy classical control expressions, as discussed here: https://github.com/quantumlib/Cirq/pull/4778/files#r774816995. The other PR was simpler and less invasive, but a bit hacky. I felt even though bigger, this seemed like the better approach and especially fits better with our future direction, and closed the other one). **Breaking Changes**: 1. The abstract method `SimulatorBase._create_partial_act_on_args` argument `log_of_measurement_results: Dict` has been changed to `classical_data: ClassicalData`. Any third-party simulators that inherit `SimulatorBase` will need to update their implementation accordingly. 2. The abstract base class `ActOnArgs.__init__` argument `log_of_measurement_results: Dict` is now copied before use. For users that depend on the pass-by-reference semantics (this should be rare), they can use the new `classical_data: ClassicalData` argument instead, which is pass-by-reference.
Allow repeated measurement keys. Implements steps 1, 2, 3, and 4 from #4274 (comment): 1. Expand ClassicalDataStore with the extra dimension 2. Remove the exception if a measurement is repeated and just toss it into the extra dimension. 3. Ensure the generated `log_of_measurement_results` grabs the most recent index. (This step "just worked" by virtue of having a default index=-1). 4. Add an optional `index` property to `KeyCondition` to specify which index to use in classical controls (default `-1`). Step 5 will be a surprisingly straightforward follow-up to this one daxfohl/Cirq@repeated...daxfohl:repeated2 (still needs fleshed out for serializing the new field etc.). Step 6 is being done in parallel in #4949 and subsequent PRs.
@daxfohl, yes, marking this complete. There will likely be follow-up changes, but the main feature is there. |
Allow repeated measurement keys. Implements steps 1, 2, 3, and 4 from quantumlib#4274 (comment): 1. Expand ClassicalDataStore with the extra dimension 2. Remove the exception if a measurement is repeated and just toss it into the extra dimension. 3. Ensure the generated `log_of_measurement_results` grabs the most recent index. (This step "just worked" by virtue of having a default index=-1). 4. Add an optional `index` property to `KeyCondition` to specify which index to use in classical controls (default `-1`). Step 5 will be a surprisingly straightforward follow-up to this one daxfohl/Cirq@repeated...daxfohl:repeated2 (still needs fleshed out for serializing the new field etc.). Step 6 is being done in parallel in quantumlib#4949 and subsequent PRs.
…lib#4806) This converts cirq.Result into an abstract base class which defines the interface provided by measurement result objects. We introduce a new class cirq.ResultDict which is the default implementation of this result type, based on a dict mapping string keys to array data. This will allow us to provide alternate implementations as needed, for example a result type that is based on a DataFrame and only converts to measurement dict on demand (cf quantumlib#4774), or a result type that is based on experimental data (such as raw IQ data) and allows accessing this raw data while also converting to the standard measurements dict on demand (see quantumlib#3868 for other possible Result implementations). Making this separation will also simplify the implementation of repeated measurement keys (quantumlib#4274), since it will allow us to define the new interface for accessing data from repeated keys separately from the implementation of how this data is stored. Review: @95-martin-orion
…mlib#4781) Adds a `ClassicalDataStore` class so we can keep track of which qubits are associated to which measurements. Closes quantumlib#3232. Initially this was created as part 14 (of 14) of https://tinyurl.com/cirq-feedforward to enable qudits in classical conditions, by storing and using dimensions of the measured qubits when calculating the integer value of each measurement when resolving sympy expressions. However it may have broader applicability. This approach also sets us up to more easily add different types of measurements (quantumlib#3233, quantumlib#4274). It will also ease the path to quantumlib#3002 and quantumlib#4449., as we can eventually pass this into `Result` rather than the raw `log_of_measurement_results` dictionary. (The return type of `_run` will have to be changed to `Sequence[C;assicalDataStoreReader]`. Related: quantumlib#887, quantumlib#3231 (open question @95-martin-orion whether this closes those or not) This PR contains a `ClassicalDataStoreReader` and `ClassicalDataStoreBase` parent "interface" for the `ClassicalDataStore` class as well. This will allow us to swap in different representations that may have different performance characteristics. See quantumlib#3808 for an example use case. This could be done by adding an optional `ClassicalDataStore` factory method argument to the `SimulatorBase` initializer, or separately to sampler classes. (Note this is an alternative to quantumlib#4778 for supporting qudits in sympy classical control expressions, as discussed here: https://github.com/quantumlib/Cirq/pull/4778/files#r774816995. The other PR was simpler and less invasive, but a bit hacky. I felt even though bigger, this seemed like the better approach and especially fits better with our future direction, and closed the other one). **Breaking Changes**: 1. The abstract method `SimulatorBase._create_partial_act_on_args` argument `log_of_measurement_results: Dict` has been changed to `classical_data: ClassicalData`. Any third-party simulators that inherit `SimulatorBase` will need to update their implementation accordingly. 2. The abstract base class `ActOnArgs.__init__` argument `log_of_measurement_results: Dict` is now copied before use. For users that depend on the pass-by-reference semantics (this should be rare), they can use the new `classical_data: ClassicalData` argument instead, which is pass-by-reference.
Allow repeated measurement keys. Implements steps 1, 2, 3, and 4 from quantumlib#4274 (comment): 1. Expand ClassicalDataStore with the extra dimension 2. Remove the exception if a measurement is repeated and just toss it into the extra dimension. 3. Ensure the generated `log_of_measurement_results` grabs the most recent index. (This step "just worked" by virtue of having a default index=-1). 4. Add an optional `index` property to `KeyCondition` to specify which index to use in classical controls (default `-1`). Step 5 will be a surprisingly straightforward follow-up to this one daxfohl/Cirq@repeated...daxfohl:repeated2 (still needs fleshed out for serializing the new field etc.). Step 6 is being done in parallel in quantumlib#4949 and subsequent PRs.
…lib#4806) This converts cirq.Result into an abstract base class which defines the interface provided by measurement result objects. We introduce a new class cirq.ResultDict which is the default implementation of this result type, based on a dict mapping string keys to array data. This will allow us to provide alternate implementations as needed, for example a result type that is based on a DataFrame and only converts to measurement dict on demand (cf quantumlib#4774), or a result type that is based on experimental data (such as raw IQ data) and allows accessing this raw data while also converting to the standard measurements dict on demand (see quantumlib#3868 for other possible Result implementations). Making this separation will also simplify the implementation of repeated measurement keys (quantumlib#4274), since it will allow us to define the new interface for accessing data from repeated keys separately from the implementation of how this data is stored. Review: @95-martin-orion
…mlib#4781) Adds a `ClassicalDataStore` class so we can keep track of which qubits are associated to which measurements. Closes quantumlib#3232. Initially this was created as part 14 (of 14) of https://tinyurl.com/cirq-feedforward to enable qudits in classical conditions, by storing and using dimensions of the measured qubits when calculating the integer value of each measurement when resolving sympy expressions. However it may have broader applicability. This approach also sets us up to more easily add different types of measurements (quantumlib#3233, quantumlib#4274). It will also ease the path to quantumlib#3002 and quantumlib#4449., as we can eventually pass this into `Result` rather than the raw `log_of_measurement_results` dictionary. (The return type of `_run` will have to be changed to `Sequence[C;assicalDataStoreReader]`. Related: quantumlib#887, quantumlib#3231 (open question @95-martin-orion whether this closes those or not) This PR contains a `ClassicalDataStoreReader` and `ClassicalDataStoreBase` parent "interface" for the `ClassicalDataStore` class as well. This will allow us to swap in different representations that may have different performance characteristics. See quantumlib#3808 for an example use case. This could be done by adding an optional `ClassicalDataStore` factory method argument to the `SimulatorBase` initializer, or separately to sampler classes. (Note this is an alternative to quantumlib#4778 for supporting qudits in sympy classical control expressions, as discussed here: https://github.com/quantumlib/Cirq/pull/4778/files#r774816995. The other PR was simpler and less invasive, but a bit hacky. I felt even though bigger, this seemed like the better approach and especially fits better with our future direction, and closed the other one). **Breaking Changes**: 1. The abstract method `SimulatorBase._create_partial_act_on_args` argument `log_of_measurement_results: Dict` has been changed to `classical_data: ClassicalData`. Any third-party simulators that inherit `SimulatorBase` will need to update their implementation accordingly. 2. The abstract base class `ActOnArgs.__init__` argument `log_of_measurement_results: Dict` is now copied before use. For users that depend on the pass-by-reference semantics (this should be rare), they can use the new `classical_data: ClassicalData` argument instead, which is pass-by-reference.
Allow repeated measurement keys. Implements steps 1, 2, 3, and 4 from quantumlib#4274 (comment): 1. Expand ClassicalDataStore with the extra dimension 2. Remove the exception if a measurement is repeated and just toss it into the extra dimension. 3. Ensure the generated `log_of_measurement_results` grabs the most recent index. (This step "just worked" by virtue of having a default index=-1). 4. Add an optional `index` property to `KeyCondition` to specify which index to use in classical controls (default `-1`). Step 5 will be a surprisingly straightforward follow-up to this one daxfohl/Cirq@repeated...daxfohl:repeated2 (still needs fleshed out for serializing the new field etc.). Step 6 is being done in parallel in quantumlib#4949 and subsequent PRs.
Is your design idea/issue related to a use case or problem? Please describe.
Cirq circuits allow doing repeated measurements. This is particularly important in error correction experiments which typically include multiple "rounds" of an error detection circuit where syndrome qubits are measured. The classical data is then used to detect and correct errors.
Each measurement gate in cirq has a key that is used to identify data for that measurement in the
cirq.Result
object. The data for a measurement is a 2D array of shape(n_repetitions, n_qubits)
where the first axis indexes the repetitions of the circuit, and the second axis indexes qubits that were measured.Currently, measurement keys within a circuit must be unique within a circuit, which leads to some complexity:
CircuitOperation
, we need to be able to remap keys so that we can distinguish measurements from a subcircuit included more than once.CircuitOperation
with repetitions, we need to included "repetition ids" to distinguish measurements coming from each repetition of the subcircuit. This leads to some complicated logic and required the introduction of thecirq.MeasurementKey
object to replace plain string keys.stim
, we want to be able to describe error "detectors" that relate successive measurements on one or more qubits. In stim, this can be done by using relative indexing of targets to specify previous gates. This essentially treats measurements as being appended to a stream (the "measurement record" in stim). In current cirq where each instance of a measurement gate may have a different key, such relative indexing does not work and we would instead have to compute the key for a specific previous measurement (which is particularly complicated in the presence of loops, for example).Describe your design idea/issue
I propose that we drop the requirement that measurement keys have to be unique. If measurements with the same key appear multiple times in a circuit (or in a looped CircuitOperation), they would get combined into a single data array in the result object. These arrays would have a new "instance" axis to account for this, so the data for each key would now be a 3D array of shape
(n_repetitions, n_instances, n_qubits)
. This data would be made available via a new dict-like attribute oncirq.Result
. For compatibility, the existingmeasurements
attribute would still be available ifn_instances
is 1 for all measurements, as is the case in all circuits that are currently supported. Would have to determine how the new format would map to a pands dataframe as in the currentcirq.Result.data
property.Another question TBD is whether measurements with the same key would be required to measure the same qubits. The simplest thing would probably be to require the same qubits (in the same order) on each instance of a particular measurement key in a circuit, as this would make it easy to interpret the result data. However, one could instead allow each instance to measure different qubits, or the same qubits in a different order, since we just need to be able to append a "row" to the result array for each measurement instance; this would put the burden on the user to interpret the data for each instance by remembering which qubits were measured each time (we would have to restrict that the same measure key cannot appear multiple times within a moment since there would be no way to order the results from measurements within a moment). I would lean toward requiring the same ordered qubits on each instance initially, though this restriction could perhaps be relaxed in the future.
The text was updated successfully, but these errors were encountered: