diff --git a/docs/source/intro_rydberg_blockade.ipynb b/docs/source/intro_rydberg_blockade.ipynb index db47534b..35cef044 100644 --- a/docs/source/intro_rydberg_blockade.ipynb +++ b/docs/source/intro_rydberg_blockade.ipynb @@ -51,7 +51,7 @@ "outputs": [], "source": [ "layers = 3\n", - "reg = pulser.Register.hexagon(layers)\n", + "reg = pulser.Register.hexagon(layers, prefix=\"q\")\n", "reg.draw(with_labels=False)" ] }, @@ -221,7 +221,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "pulserenv", "language": "python", "name": "python3" }, @@ -235,7 +235,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.12.3" } }, "nbformat": 4, diff --git a/pulser-core/pulser/devices/_device_datacls.py b/pulser-core/pulser/devices/_device_datacls.py index 0a248125..203cb6cf 100644 --- a/pulser-core/pulser/devices/_device_datacls.py +++ b/pulser-core/pulser/devices/_device_datacls.py @@ -534,7 +534,7 @@ def _validate_coords( ), kind: Literal["atoms", "traps"] = "atoms", ) -> None: - ids = list(coords_dict.keys()) + ids = [str(id) for id in list(coords_dict.keys())] coords = list(map(pm.AbstractArray, coords_dict.values())) if kind == "atoms" and not ( "max_atom_num" in self._optional_parameters @@ -763,7 +763,7 @@ def _specs(self, for_docs: bool = False) -> str: ( "\t" + r"- Maximum :math:`\Omega`:" - + f" {float(cast(float,ch.max_amp)):.4g} rad/µs" + + f" {float(cast(float, ch.max_amp)):.4g} rad/µs" ), ( ( @@ -776,7 +776,7 @@ def _specs(self, for_docs: bool = False) -> str: else ( "\t" + r"- Bottom :math:`|\delta|`:" - + f" {float(cast(float,ch.bottom_detuning)):.4g}" + + f" {float(cast(float, ch.bottom_detuning)):.4g}" + " rad/µs" ) ), diff --git a/pulser-core/pulser/register/_reg_drawer.py b/pulser-core/pulser/register/_reg_drawer.py index a50ce41d..155c7e8c 100644 --- a/pulser-core/pulser/register/_reg_drawer.py +++ b/pulser-core/pulser/register/_reg_drawer.py @@ -93,8 +93,8 @@ def _draw_2D( if dmm_qubits: dmm_pos = [] - for i, c in zip(ids, pos): - if i in dmm_qubits.keys(): + for id, c in zip(ids, pos): + if id in dmm_qubits.keys(): dmm_pos.append(c) dmm_arr = np.array(dmm_pos) max_weight = max(dmm_qubits.values()) diff --git a/pulser-core/pulser/register/base_register.py b/pulser-core/pulser/register/base_register.py index d01253db..9b30c33b 100644 --- a/pulser-core/pulser/register/base_register.py +++ b/pulser-core/pulser/register/base_register.py @@ -16,6 +16,7 @@ from __future__ import annotations import json +import warnings from abc import ABC, abstractmethod from collections.abc import Iterable, Mapping from collections.abc import Sequence as abcSequence @@ -44,7 +45,7 @@ from pulser.register.register_layout import RegisterLayout T = TypeVar("T", bound="BaseRegister") -QubitId = Union[int, str] +QubitId = str class _LayoutInfo(NamedTuple): @@ -77,6 +78,16 @@ def __init__( [pm.AbstractArray(v, dtype=float) for v in qubits.values()] ) self._ids: tuple[QubitId, ...] = tuple(qubits.keys()) + if any(not isinstance(id, str) for id in self._ids): + warnings.simplefilter("always") + warnings.warn( + "Usage of `int`s or any non-`str`types as `QubitId`s will be " + "deprecated. Define your `QubitId`s as `str`s, prefer setting " + "`prefix='q'` when using classmethods, as that will become the" + " new default once `int` qubit IDs become invalid.", + DeprecationWarning, + stacklevel=2, + ) self._layout_info: Optional[_LayoutInfo] = None self._init_kwargs(**kwargs) diff --git a/pulser-core/pulser/register/register_layout.py b/pulser-core/pulser/register/register_layout.py index f543e7e1..8dd6e547 100644 --- a/pulser-core/pulser/register/register_layout.py +++ b/pulser-core/pulser/register/register_layout.py @@ -172,7 +172,7 @@ def draw( draw_graph=draw_graph, draw_half_radius=draw_half_radius, ) - ids = list(range(self.number_of_traps)) + ids = [str(i) for i in range(self.number_of_traps)] if self.dimensionality == 2: fig, ax = self._initialize_fig_axes( coords, diff --git a/pulser-core/pulser/register/weight_maps.py b/pulser-core/pulser/register/weight_maps.py index f2d146e1..d0c67f24 100644 --- a/pulser-core/pulser/register/weight_maps.py +++ b/pulser-core/pulser/register/weight_maps.py @@ -123,7 +123,9 @@ def draw( pos = self.trap_coordinates custom_ax = custom_ax or cast(Axes, self._initialize_fig_axes(pos)[1]) - labels_ = labels if labels is not None else list(range(len(pos))) + labels_ = ( + labels if labels is not None else [str(i) for i in range(len(pos))] + ) super()._draw_2D( custom_ax, diff --git a/pulser-core/pulser/sequence/sequence.py b/pulser-core/pulser/sequence/sequence.py index 11334dcc..0f1a213d 100644 --- a/pulser-core/pulser/sequence/sequence.py +++ b/pulser-core/pulser/sequence/sequence.py @@ -1344,7 +1344,7 @@ def target_index( Args: qubits: The new target for this channel. Must correspond to a - qubit index or an collection of qubit indices, when multi-qubit + qubit index or a collection of qubit indices, when multi-qubit addressing is possible. A qubit index is a number between 0 and the number of qubits. It is then converted to a Qubit ID using the order in which @@ -2057,7 +2057,7 @@ def _add( @seq_decorators.block_if_measured def _target( self, - qubits: Union[Collection[QubitId], QubitId, Parametrized], + qubits: Union[Collection[QubitId | int], QubitId | int, Parametrized], channel: str, _index: bool = False, ) -> None: @@ -2105,7 +2105,7 @@ def _target( self._schedule.add_target(qubit_ids_set, channel) def _check_qubits_give_ids( - self, *qubits: Union[QubitId, Parametrized], _index: bool = False + self, *qubits: Union[QubitId, int, Parametrized], _index: bool = False ) -> set[QubitId]: if _index: if self.is_parametrized(): @@ -2158,7 +2158,7 @@ def _delay( def _phase_shift( self, phi: float | Parametrized, - *targets: QubitId | Parametrized, + *targets: QubitId | int | Parametrized, basis: str, _index: bool = False, ) -> None: diff --git a/pyproject.toml b/pyproject.toml index a4abb7d5..b7107417 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ filterwarnings = [ "error", # Except these particular warnings, which are ignored 'ignore:A duration of \d+ ns is not a multiple of:UserWarning', + 'ignore:Usage of `int`s or any non-`str`types as `QubitId`s:DeprecationWarning', ] [build-system] diff --git a/tests/test_abstract_repr.py b/tests/test_abstract_repr.py index 0d8874e4..f218fe77 100644 --- a/tests/test_abstract_repr.py +++ b/tests/test_abstract_repr.py @@ -820,6 +820,9 @@ def test_exceptions(self, sequence): UserWarning, match="converts all qubit ID's to strings" ), pytest.raises( AbstractReprError, match="Name collisions encountered" + ), pytest.warns( + DeprecationWarning, + match="Usage of `int`s or any non-`str`types as `QubitId`s", ): Register({"0": (0, 0), 0: (20, 20)})._to_abstract_repr() diff --git a/tests/test_dmm.py b/tests/test_dmm.py index f03df88b..6927765c 100644 --- a/tests/test_dmm.py +++ b/tests/test_dmm.py @@ -14,7 +14,7 @@ from __future__ import annotations import re -from typing import cast +from typing import Union, cast from unittest.mock import patch import numpy as np @@ -37,7 +37,9 @@ def layout(self) -> RegisterLayout: @pytest.fixture def register(self, layout: RegisterLayout) -> BaseRegister: - return layout.define_register(0, 1, 2, 3, qubit_ids=(0, 1, 2, 3)) + return layout.define_register( + 0, 1, 2, 3, qubit_ids=("0", "1", "2", "3") + ) @pytest.fixture def map_reg(self, layout: RegisterLayout) -> MappableRegister: @@ -63,7 +65,7 @@ def slm_map( ) -> DetuningMap: return layout.define_detuning_map(slm_dict) - @pytest.mark.parametrize("bad_key", [{"1": 1.0}, {4: 1.0}]) + @pytest.mark.parametrize("bad_key", [{1: 1.0}, {"4": 1.0}]) def test_define_detuning_map( self, layout: RegisterLayout, @@ -72,6 +74,13 @@ def test_define_detuning_map( bad_key: dict, ): for reg in (layout, map_reg): + if type(list(bad_key.keys())[0]) == int: + with pytest.raises( + ValueError, + match="'trap_coordinates' must be an array or list", + ): + reg.define_detuning_map(bad_key) # type: ignore + continue with pytest.raises( ValueError, match=re.escape( @@ -91,7 +100,7 @@ def test_define_detuning_map( def test_qubit_weight_map(self, register): # Purposefully unsorted - qid_weight_map = {1: 1.0, 0: 0.1, 3: 0.4} + qid_weight_map = {"1": 1.0, "0": 0.1, "3": 0.4} sorted_qids = sorted(qid_weight_map) det_map = register.define_detuning_map(qid_weight_map) qubits = register.qubits @@ -104,7 +113,7 @@ def test_qubit_weight_map(self, register): # We recover the original qid_weight_map (and undefined qids show as 0) assert det_map.get_qubit_weight_map(qubits) == { **qid_weight_map, - 2: 0.0, + "2": 0.0, } tri_layout = TriangularLatticeLayout(100, spacing=5) @@ -172,8 +181,12 @@ def test_detuning_map_bad_init( ): DetuningMap([(0, 0), (1, 0)], [0]) - bad_weights = {0: -1.0, 1: 1.0, 2: 1.0} for reg in (layout, map_reg, register): + bad_weights: dict[int | str, float] + if reg == register: + bad_weights = {"0": -1.0, "1": 1.0, "2": 1.0} + else: + bad_weights = {0: -1.0, 1: 1.0, 2: 1.0} with pytest.raises( ValueError, match="All weights must be between 0 and 1." ): @@ -187,11 +200,22 @@ def test_init( det_dict: dict[int, float], slm_dict: dict[int, float], ): + for reg in (layout, map_reg, register): for detuning_map_dict in (det_dict, slm_dict): + reg_det_map_dict: dict[int | str, float] + if reg == register: + reg_det_map_dict = { + str(id): weight + for (id, weight) in detuning_map_dict.items() + } + else: + reg_det_map_dict = cast( + dict[Union[int, str], float], detuning_map_dict + ) detuning_map = cast( DetuningMap, - reg.define_detuning_map(detuning_map_dict), # type: ignore + reg.define_detuning_map(reg_det_map_dict), # type: ignore ) assert np.all( [ @@ -227,7 +251,7 @@ def test_draw(self, det_map, slm_map, patch_plt_show, with_labels): )[1], np.array(slm_map.trap_coordinates), [ - i + str(i) for i, _ in enumerate(cast(list, slm_map.trap_coordinates)) ], with_labels=True, diff --git a/tests/test_json.py b/tests/test_json.py index b211c06d..4ee83a8c 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -119,15 +119,24 @@ def test_detuning_map(): @pytest.mark.parametrize( - "reg", + "reg_dict", [ - Register(dict(enumerate([(2, 3), (5, 1), (10, 0)]))), - Register3D({3: (2, 3, 4), 4: (3, 4, 5), 2: (4, 5, 7)}), + dict(enumerate([(2, 3), (5, 1), (10, 0)])), + {3: (2, 3, 4), 4: (3, 4, 5), 2: (4, 5, 7)}, ], ) -def test_register_numbered_keys(reg): +def test_register_numbered_keys(reg_dict): + with pytest.warns( + DeprecationWarning, + match="Usage of `int`s or any non-`str`types as `QubitId`s", + ): + reg = (Register if len(reg_dict[2]) == 2 else Register3D)(reg_dict) j = json.dumps(reg, cls=PulserEncoder) - decoded_reg = json.loads(j, cls=PulserDecoder) + with pytest.warns( + DeprecationWarning, + match="Usage of `int`s or any non-`str`types as `QubitId`s", + ): + decoded_reg = json.loads(j, cls=PulserDecoder) assert reg == decoded_reg assert all([type(i) is int for i in decoded_reg.qubit_ids]) diff --git a/tests/test_paramseq.py b/tests/test_paramseq.py index 976e246f..7048a20a 100644 --- a/tests/test_paramseq.py +++ b/tests/test_paramseq.py @@ -24,7 +24,7 @@ from pulser.parametrized.variable import VariableItem from pulser.waveforms import BlackmanWaveform -reg = Register.rectangle(4, 3) +reg = Register.rectangle(4, 3, prefix="q") device = DigitalAnalogDevice @@ -50,10 +50,10 @@ def test_parametrized_channel_initial_target(): var = sb.declare_variable("var") sb.declare_channel("ch1", "rydberg_local") sb.target_index(var, "ch1") - sb.declare_channel("ch0", "raman_local", initial_target=0) + sb.declare_channel("ch0", "raman_local", initial_target="q0") assert sb._calls[-1].name == "declare_channel" assert sb._to_build_calls[-1].name == "target" - assert sb._to_build_calls[-1].args == (0, "ch0") + assert sb._to_build_calls[-1].args == ("q0", "ch0") def test_stored_calls(): @@ -125,7 +125,9 @@ def test_stored_calls(): sb.target_index(q_var, "ch1") sb2 = Sequence(reg, MockDevice) - sb2.declare_channel("ch1", "rydberg_local", initial_target={3, 4, 5}) + sb2.declare_channel( + "ch1", "rydberg_local", initial_target={"q3", "q4", "q5"} + ) q_var2 = sb2.declare_variable("q_var2", size=5, dtype=int) var2 = sb2.declare_variable("var2") assert sb2._building @@ -229,7 +231,7 @@ def test_str(): def test_screen(): sb = Sequence(reg, device) sb.declare_channel("ch1", "rydberg_global") - assert sb.current_phase_ref(4, basis="ground-rydberg") == 0 + assert sb.current_phase_ref("q4", basis="ground-rydberg") == 0 var = sb.declare_variable("var") sb.delay(var, "ch1") with pytest.raises(RuntimeError, match="can't be called in parametrized"): @@ -239,7 +241,7 @@ def test_screen(): def test_parametrized_in_eom_mode(mod_device): # Case 1: Sequence becomes parametrized while in EOM mode seq = Sequence(reg, mod_device) - seq.declare_channel("ch0", "rydberg_local", initial_target=0) + seq.declare_channel("ch0", "rydberg_local", initial_target="q0") assert not seq.is_in_eom_mode("ch0") seq.enable_eom_mode("ch0", amp_on=2.0, detuning_on=0.0) @@ -278,8 +280,8 @@ def test_parametrized_before_eom_mode(mod_device): # Case 2: Sequence is parametrized before entering EOM mode seq = Sequence(reg, mod_device) - seq.declare_channel("ch0", "rydberg_local", initial_target=0) - seq.declare_channel("raman", "raman_local", initial_target=2) + seq.declare_channel("ch0", "rydberg_local", initial_target="q0") + seq.declare_channel("raman", "raman_local", initial_target="q2") amp = seq.declare_variable("amp", dtype=float) seq.add(Pulse.ConstantPulse(200, amp, -1, 0), "ch0") diff --git a/tests/test_sequence.py b/tests/test_sequence.py index a871ab77..d13d5bc3 100644 --- a/tests/test_sequence.py +++ b/tests/test_sequence.py @@ -1614,8 +1614,11 @@ def test_str(reg, device, mod_device, det_map): measure_msg = "\n\nMeasured in basis: digital" assert seq.__str__() == msg_ch0 + msg_ch1 + msg_det_map + measure_msg - - seq2 = Sequence(Register({"q0": (0, 0), 1: (5, 5)}), device) + with pytest.warns( + DeprecationWarning, + match="Usage of `int`s or any non-`str`types as `QubitId`s", + ): + seq2 = Sequence(Register({"q0": (0, 0), 1: (5, 5)}), device) seq2.declare_channel("ch1", "rydberg_global") with pytest.raises( NotImplementedError, diff --git a/tests/test_sequence_sampler.py b/tests/test_sequence_sampler.py index 8363825e..6b27d5be 100644 --- a/tests/test_sequence_sampler.py +++ b/tests/test_sequence_sampler.py @@ -201,8 +201,8 @@ def test_modulation(mod_seq: pulser.Sequence) -> None: def test_modulation_local(mod_device): - seq = pulser.Sequence(pulser.Register.square(2), mod_device) - seq.declare_channel("ch0", "rydberg_local", initial_target=0) + seq = pulser.Sequence(pulser.Register.square(2, prefix="q"), mod_device) + seq.declare_channel("ch0", "rydberg_local", initial_target="q0") ch_obj = seq.declared_channels["ch0"] pulse1 = Pulse.ConstantPulse(500, 1, -1, 0) pulse2 = Pulse.ConstantPulse(200, 2.5, 0, 0) @@ -210,7 +210,7 @@ def test_modulation_local(mod_device): seq.add(pulse1, "ch0") seq.delay(partial_fall, "ch0") seq.add(pulse2, "ch0") - seq.target(1, "ch0") + seq.target("q1", "ch0") seq.add(pulse1, "ch0") input_samples = sample(seq) @@ -236,7 +236,8 @@ def test_modulation_local(mod_device): samples_dict = output_samples.to_nested_dict() for qty in ("amp", "det", "phase"): combined = sum( - samples_dict["Local"]["ground-rydberg"][t][qty] for t in range(2) + samples_dict["Local"]["ground-rydberg"][f"q{t}"][qty] + for t in range(2) ) np.testing.assert_array_equal(getattr(out_ch_samples, qty), combined) diff --git a/tutorials/advanced_features/Interpolated Waveforms.ipynb b/tutorials/advanced_features/Interpolated Waveforms.ipynb index 163a71b2..fadf97ec 100644 --- a/tutorials/advanced_features/Interpolated Waveforms.ipynb +++ b/tutorials/advanced_features/Interpolated Waveforms.ipynb @@ -158,7 +158,7 @@ }, "outputs": [], "source": [ - "reg = Register.square(1)\n", + "reg = Register.square(1, prefix=\"q\")\n", "param_seq = Sequence(reg, AnalogDevice)\n", "param_seq.declare_channel(\"rydberg_global\", \"rydberg_global\", initial_target=0)\n", "amp_vals = param_seq.declare_variable(\"amp_vals\", size=5, dtype=float)\n", diff --git a/tutorials/advanced_features/Output Modulation and EOM Mode.ipynb b/tutorials/advanced_features/Output Modulation and EOM Mode.ipynb index 944598fb..9f1c7b7e 100644 --- a/tutorials/advanced_features/Output Modulation and EOM Mode.ipynb +++ b/tutorials/advanced_features/Output Modulation and EOM Mode.ipynb @@ -276,7 +276,7 @@ "source": [ "from pulser.devices import AnalogDevice\n", "\n", - "seq = Sequence(Register.square(2, spacing=6), AnalogDevice)\n", + "seq = Sequence(Register.square(2, spacing=6, prefix=\"q\"), AnalogDevice)\n", "seq.declare_channel(\"rydberg\", \"rydberg_global\")\n", "\n", "seq.add(Pulse.ConstantPulse(100, 1, 0, 0), \"rydberg\")\n", diff --git a/tutorials/advanced_features/Virtual Devices.ipynb b/tutorials/advanced_features/Virtual Devices.ipynb index 75b80f62..1dc78343 100644 --- a/tutorials/advanced_features/Virtual Devices.ipynb +++ b/tutorials/advanced_features/Virtual Devices.ipynb @@ -142,7 +142,9 @@ "# Enable the multiple declaration of a channel in a sequence\n", "VirtualAnalog3D = replace(VirtualAnalog3D, reusable_channels=True)\n", "# Creating a square register\n", - "reg = Register.square(4, spacing=5) # 4x4 array with atoms 5 um apart\n", + "reg = Register.square(\n", + " 4, spacing=5, prefix=\"q\"\n", + ") # 4x4 array with atoms 5 um apart\n", "# Building a sequence with the register and the virtual device\n", "seq = Sequence(reg, VirtualAnalog3D)\n", "# Declare twice the channel \"rydberg_global\"\n", diff --git a/tutorials/applications/QAOA and QAA to solve a QUBO problem.ipynb b/tutorials/applications/QAOA and QAA to solve a QUBO problem.ipynb index 624fc894..254639ca 100644 --- a/tutorials/applications/QAOA and QAA to solve a QUBO problem.ipynb +++ b/tutorials/applications/QAOA and QAA to solve a QUBO problem.ipynb @@ -183,7 +183,7 @@ "metadata": {}, "outputs": [], "source": [ - "qubits = dict(enumerate(coords))\n", + "qubits = {f\"q{i}\": coord for (i, coord) in enumerate(coords)}\n", "reg = Register(qubits)\n", "reg.draw(\n", " blockade_radius=DigitalAnalogDevice.rydberg_blockade_radius(1.0),\n", diff --git a/tutorials/creating_sequences.ipynb b/tutorials/creating_sequences.ipynb index ff9c8681..b5fc3aaf 100644 --- a/tutorials/creating_sequences.ipynb +++ b/tutorials/creating_sequences.ipynb @@ -43,7 +43,7 @@ "square -= np.mean(square, axis=0)\n", "square *= 5\n", "\n", - "qubits = dict(enumerate(square))\n", + "qubits = {f\"q{i}\": point for (i, point) in enumerate(square)}\n", "reg = pulser.Register(qubits)" ] }, @@ -103,7 +103,9 @@ "metadata": {}, "outputs": [], "source": [ - "reg3 = pulser.Register.square(4, spacing=5) # 4x4 array with atoms 5 um apart\n", + "reg3 = pulser.Register.square(\n", + " 4, spacing=5, prefix=\"q\"\n", + ") # 4x4 array with atoms 5 um apart\n", "reg3.draw()" ] }, @@ -176,7 +178,7 @@ "print(\"Available channels after declaring 'ch0':\")\n", "pprint(seq.available_channels)\n", "\n", - "seq.declare_channel(\"ch1\", \"rydberg_local\", initial_target=4)\n", + "seq.declare_channel(\"ch1\", \"rydberg_local\", initial_target=\"q4\")\n", "print(\"\\nAvailable channels after declaring 'ch1':\")\n", "pprint(seq.available_channels)" ] @@ -219,7 +221,7 @@ "metadata": {}, "outputs": [], "source": [ - "seq.target(1, \"ch0\")" + "seq.target(\"q1\", \"ch0\")" ] }, { @@ -406,7 +408,7 @@ "metadata": {}, "outputs": [], "source": [ - "seq.target(4, \"ch0\")\n", + "seq.target(\"q4\", \"ch0\")\n", "seq.add(complex_pulse, \"ch0\")\n", "\n", "print(\"Current Schedule:\")\n", @@ -436,7 +438,7 @@ "metadata": {}, "outputs": [], "source": [ - "seq.target(0, \"ch1\")\n", + "seq.target(\"q0\", \"ch1\")\n", "seq.add(simple_pulse, \"ch1\", protocol=\"min-delay\")\n", "seq.add(simple_pulse, \"ch1\", protocol=\"wait-for-all\")\n", "\n", @@ -465,7 +467,7 @@ "metadata": {}, "outputs": [], "source": [ - "seq.target(0, \"ch0\")\n", + "seq.target(\"q0\", \"ch0\")\n", "seq.add(complex_pulse, \"ch0\", protocol=\"no-delay\")\n", "\n", "print(\"Current Schedule:\")\n", diff --git a/tutorials/quantum_simulation/Microwave-engineering of programmable XXZ Hamiltonians in arrays of Rydberg atoms.ipynb b/tutorials/quantum_simulation/Microwave-engineering of programmable XXZ Hamiltonians in arrays of Rydberg atoms.ipynb index a57a92ec..2d0aad62 100644 --- a/tutorials/quantum_simulation/Microwave-engineering of programmable XXZ Hamiltonians in arrays of Rydberg atoms.ipynb +++ b/tutorials/quantum_simulation/Microwave-engineering of programmable XXZ Hamiltonians in arrays of Rydberg atoms.ipynb @@ -108,7 +108,7 @@ "source": [ "# We take two atoms distant by 10 ums.\n", "coords = np.array([[0, 0], [10, 0]])\n", - "qubits = dict(enumerate(coords))\n", + "qubits = {f\"q{i}\": coord for (i, coord) in enumerate(coords)}\n", "reg = Register(qubits)\n", "\n", "seq = Sequence(reg, MockDevice)\n", @@ -284,7 +284,7 @@ "outputs": [], "source": [ "# Line geometry\n", - "reg = Register.rectangle(1, N_at, 10)\n", + "reg = Register.rectangle(1, N_at, 10, prefix=\"q\")\n", "magnetizations_obc = np.zeros((N_at, N_cycles), dtype=float)\n", "correl_obc = np.zeros(N_cycles, dtype=float)\n", "for m in range(N_cycles): # Runtime close to 2 min!\n", @@ -336,7 +336,7 @@ " ]\n", " )\n", ")\n", - "reg = Register.from_coordinates(coords)\n", + "reg = Register.from_coordinates(coords, prefix=\"q\")\n", "\n", "magnetizations_pbc = np.zeros((N_at, N_cycles), dtype=float)\n", "correl_pbc = np.zeros(N_cycles, dtype=float)\n", diff --git a/tutorials/quantum_simulation/Preparing state with antiferromagnetic order in the Ising model.ipynb b/tutorials/quantum_simulation/Preparing state with antiferromagnetic order in the Ising model.ipynb index 67ec882b..de35b006 100644 --- a/tutorials/quantum_simulation/Preparing state with antiferromagnetic order in the Ising model.ipynb +++ b/tutorials/quantum_simulation/Preparing state with antiferromagnetic order in the Ising model.ipynb @@ -467,7 +467,7 @@ " ) # To be a multiple of the clock period of AnalogDevice (4ns)\n", "\n", " R_interatomic = AnalogDevice.rydberg_blockade_radius(U)\n", - " reg = Register.rectangle(N, N, R_interatomic)\n", + " reg = Register.rectangle(N, N, R_interatomic, prefix=\"q\")\n", "\n", " # Pulse Sequence\n", " rise = Pulse.ConstantDetuning(\n", diff --git a/tutorials/quantum_simulation/Shadow estimation for VQS.ipynb b/tutorials/quantum_simulation/Shadow estimation for VQS.ipynb index 5c6a9e62..985e75e6 100644 --- a/tutorials/quantum_simulation/Shadow estimation for VQS.ipynb +++ b/tutorials/quantum_simulation/Shadow estimation for VQS.ipynb @@ -1,1408 +1,1403 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Efficient estimation techniques for Variational Quantum Simulation" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Introduction" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "$\\newcommand{\\ket}[1]{\\left|#1\\right>} \\newcommand{\\bra}[1]{\\left<#1\\right|}$\n", - "This notebook's purpose is to introduce the concept of classical shadow estimation, as well as its use in **VQS** (**V**ariational **Q**uantum **S**imulation). This technique, introduced in [this article by Huang, Kueng and Preskill](https://arxiv.org/abs/2002.08953), is used for efficiently estimating multiple observables, and is extremely powerful in that regard, asymptotically reaching theoretical lower bounds of quantum information theory regarding the number of required samples of a given state for estimation ([see here for details](https://arxiv.org/abs/2101.02464)). \n", - "\n", - "The primary goal of this notebook is to estimate the groundstate energy of the $H_2$ molecule, using a VQS. We will first implement the method of random classical shadows in Python. Then, we'll introduce its derandomized counterpart, which is particularly useful in our setting. We'll finally describe the VQS, and benchmark the estimation methods we introduced for computing the molecule's energy. This notebook draws some inspiration from [this PennyLane Jupyter notebook](https://pennylane.ai/qml/demos/tutorial_classical_shadows.html) on quantum machine learning and classical shadows." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Random classical shadows" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Main ideas and implementation" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Classical shadow estimation relies on the fact that for a particular\n", - "choice of measurement, we can efficiently store snapshots of the state\n", - "that contain enough information to accurately predict linear functions\n", - "of observables.\n", - "\n", - "Let us consider an $n$-qubit quantum state $\\rho$ (prepared by a\n", - "pulse sequence) and apply a random unitary $U$ to the state:\n", - "\n", - "$$\\rho \\to U \\rho U^\\dagger.$$\n", - "\n", - "Next, we measure in the computational basis and obtain a bit string of\n", - "outcomes $|b\\rangle = |0011\\ldots10\\rangle$. If the unitaries $U$ are\n", - "chosen at random from a particular ensemble, then we can store the\n", - "reverse operation $U^\\dagger |b\\rangle\\langle b| U$ efficiently in\n", - "classical memory. We call this a *snapshot* of the state. Moreover, we\n", - "can view the average over these snapshots as a measurement channel:\n", - "\n", - "$$\\mathbb{E}\\left[U^\\dagger |b\\rangle\\langle b| U\\right] = \\mathcal{M}(\\rho).$$\n", - "\n", - "We restrict ourselves to unitary ensembles that define a tomographically complete set of\n", - "measurements (i.e $\\mathcal{M}$ is invertible), therefore :\n", - "\n", - "$$\\rho = \\mathbb{E}\\left[\\mathcal{M}^{-1}\\left(U^\\dagger |b\\rangle\\langle b| U \\right)\\right].$$\n", - "\n", - "If we apply the procedure outlined above $N$ times, then the collection\n", - "of inverted snapshots is what we call the *classical shadow*\n", - "\n", - "$$S(\\rho,N) = \\left\\{\\hat{\\rho}_1= \\mathcal{M}^{-1}\\left(U_1^\\dagger |b_1\\rangle\\langle b_1| U_1 \\right)\n", - ",\\ldots, \\hat{\\rho}_N= \\mathcal{M}^{-1}\\left(U_N^\\dagger |b_N\\rangle\\langle b_N| U_N \\right)\n", - "\\right\\}.$$\n", - "\n", - "Since the shadow approximates $\\rho$, we can now estimate **any**\n", - "observable with the empirical mean:\n", - "\n", - "$$\\langle O \\rangle = \\frac{1}{N}\\sum_i \\text{Tr}{\\hat{\\rho}_i O}.$$\n", - "\n", - "We will be using a median-of-means procedure in practice." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We start by defining several useful quantities, such as the unitary matrices associated with Pauli measurements : the Hadamard matrix, change of basis from $\\{\\ket{0}, \\ket{1}\\}$ to the eigenbasis of $\\sigma_X$, $\\{\\ket{+}, \\ket{-}\\}$, and its $\\sigma_Y, \\sigma_Z$ counterparts. We will then draw randomly from this tomographically complete set of $3$ unitaries.\n", - "\n", - "Note that we will need $4$ qubits for our VQS problem : we will explain the mapping from the molecule to qubits later." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import qutip\n", - "import matplotlib.pyplot as plt\n", - "from scipy.optimize import minimize\n", - "\n", - "from pulser import Register, Sequence, Pulse\n", - "from pulser.devices import DigitalAnalogDevice\n", - "from pulser_simulation import QutipEmulator" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "num_qubits = 4\n", - "zero_state = qutip.basis(2, 0).proj()\n", - "one_state = qutip.basis(2, 1).proj()\n", - "hadamard = 1 / np.sqrt(2) * qutip.Qobj([[1.0, 1.0], [1.0, -1.0]])\n", - "h_mul_phase = qutip.Qobj(np.array([[1.0, 1], [1.0j, -1.0j]])) / np.sqrt(2)\n", - "unitary_ensemble = [hadamard, h_mul_phase, qutip.qeye(2)]\n", - "\n", - "g = qutip.basis(2, 1)\n", - "r = qutip.basis(2, 0)\n", - "n = r * r.dag()\n", - "\n", - "sx = qutip.sigmax()\n", - "sy = qutip.sigmay()\n", - "sz = qutip.sigmaz()\n", - "\n", - "gggg = qutip.tensor([g, g, g, g])\n", - "ggrr = qutip.tensor([g, g, r, r])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We first define a function that spits out a random bitstring sampled from a given density matrix." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "def measure_bitstring(state):\n", - " \"\"\"Auxiliary function that returns a bitstring according to the measure of a quantum state.\"\"\"\n", - " probs = np.real(state.diag())\n", - " probs /= np.sum(probs)\n", - " x = np.nonzero(np.random.multinomial(1, probs))[0][0]\n", - " bitstring = np.binary_repr(x, num_qubits)\n", - " return bitstring" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will need to compute the number of shadows needed given :\n", - "\n", - "* A list of observables $o_i$\n", - "* Desired precision on expectation values $\\epsilon$ : if $\\tilde{o}_i$ is the estimated expectation value for observable $o_i$, we wish for $|Tr(o_i \\rho) - \\tilde{o}_i| \\leq \\epsilon$\n", - "* Failure probability $\\delta$ : we wish for the above equation to be satisfied with probability $1-\\delta$\n", - "\n", - "Precise formulae are given in [Huang et al.](https://arxiv.org/abs/2002.08953)\n", - "The integer $K$ returned by the function will serve as the number of blocks in our median of means procedure afterwards." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "def compute_shadow_size(delta, epsilon, observables):\n", - " \"\"\"Helper function.\n", - "\n", - " Computes both the number of shadows needed as well as the size of blocks needed\n", - " for the median_of_means method in order to approximate the expectation value of M\n", - " (linear) observables with additive error epsilon and fail probability delta.\n", - "\n", - " Args:\n", - " delta (float): Failure probability.\n", - " epsilon (float): Additive error on expectation values.\n", - " observables (list[qutip.Qobj]): Observables the expectation value of which is to be computed.\n", - " \"\"\"\n", - " M = len(observables)\n", - " K = 2 * np.log(2 * M / delta)\n", - " shadow_norm = (\n", - " lambda op: np.linalg.norm(\n", - " op - np.trace(op) / 2 ** int(np.log2(op.shape[0])), ord=np.inf\n", - " )\n", - " ** 2\n", - " )\n", - " # Theoretical number of shadows per cluster in the median of means procedure :\n", - " # N = 34 * max(shadow_norm(o) for o in observables) / epsilon ** 2\n", - " # We use N = 20 here to allow for quick simulation\n", - " N = 20\n", - " return int(np.ceil(N * K)), int(K)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we design a function that returns snapshots (bitstrings) of the rotated state as well as the sampled unitaries used to rotate the state $\\rho$." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "def calculate_classical_shadow(rho, shadow_size):\n", - " \"\"\"\n", - " Given a state rho, creates a collection of snapshots consisting of a bit string\n", - " and the index of a unitary operation.\n", - "\n", - " Returns:\n", - " Tuple of two numpy arrays. The first array contains measurement outcomes as bitstrings\n", - " while the second array contains the index for the sampled Pauli's (0,1,2=X,Y,Z).\n", - " \"\"\"\n", - " # sample random Pauli measurements uniformly\n", - " unitary_ids = np.random.randint(0, 3, size=(shadow_size, num_qubits))\n", - " outcomes = []\n", - " for ns in range(shadow_size):\n", - " unitmat = qutip.tensor(\n", - " [unitary_ensemble[unitary_ids[ns, i]] for i in range(num_qubits)]\n", - " )\n", - " outcomes.append(measure_bitstring(unitmat.dag() * rho * unitmat))\n", - "\n", - " # combine the computational basis outcomes and the sampled unitaries\n", - " return (outcomes, unitary_ids)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We then reconstruct an estimate of the quantum state from the sampled bitstrings, using the inverse quantum channel $\\mathcal{M}^{-1}$ defined above. In the particular case of Pauli measurements, we can actually compute the inverse channel : \n", - "\n", - "$$\\mathcal{M}^{-1} = \\otimes_{i=1}^n (3 U_i \\ket{b_i}\\bra{b_i} U^\\dagger_i - \\mathbb{1}_2)$$\n", - "\n", - "where $i$ runs over all qubits : $\\ket{b_i}$, $b_i \\in \\{0,1\\}$, is the single-bit snapshot of qubit $i$ and $U_i$ is the sampled unitary corresponding to the snapshot, acting on qubit $i$." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "def snapshot_state(outcome_ns, unitary_ids_ns):\n", - " \"\"\"\n", - " Reconstructs an estimate of a state from a single snapshot in a shadow.\n", - "\n", - " Implements Eq. (S44) from https://arxiv.org/pdf/2002.08953.pdf\n", - "\n", - " Args:\n", - " outcome_ns: Bitstring at ns\n", - " unitary_ids_ns: Rotation applied at ns.\n", - "\n", - " Returns:\n", - " Reconstructed snapshot.\n", - " \"\"\"\n", - " state_list = []\n", - "\n", - " for k in range(num_qubits):\n", - " op = unitary_ensemble[unitary_ids_ns[k]]\n", - " b = zero_state if outcome_ns[k] == \"0\" else one_state\n", - " state_list.append(3 * op * b * op.dag() - qutip.qeye(2))\n", - "\n", - " return qutip.tensor(state_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We finally write a median of means procedure. We feed it an observable, the list of snapshots computed above and the number of blocks needed. It returns the median of the means of the observable acting on the snapshots in each block." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "def _median_of_means(obs, snap_list, K):\n", - " if K > len(snap_list): # preventing the n_blocks > n_observations\n", - " K = int(np.ceil(len(snap_list) / 2))\n", - " # dividing seq in K random blocks\n", - " indic = np.array((list(range(K)) * int(len(snap_list) / K)))\n", - " np.random.shuffle(indic)\n", - " # computing and saving mean per block\n", - " means = []\n", - " for block in range(K):\n", - " states = [snap_list[i] for i in np.where(indic == block)[0]]\n", - " exp = qutip.expect(obs, states)\n", - " means.append(np.mean(exp))\n", - " return np.median(means)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Reconstructing a given quantum state" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us try out the efficiency of this method. We will reconstruct a given density matrix from classical shadows estimation, and observe the evolution of the trace distance between the original state and its reconstruction according to the number of shadows used." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "def state_reconstruction(snaps):\n", - " return sum(snaps) / len(snaps)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Original density matrix :\n", - "[[0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]\n", - " [0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]\n", - " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", - " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]]\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Shadow reconstruction :\n", - "[[0.49+0.j 0.51+0.j 0.01+0.j 0.02+0.01j]\n", - " [0.51-0.j 0.5 +0.j 0. -0.01j 0. -0.01j]\n", - " [0.01-0.j 0. +0.01j 0.01+0.j 0. +0.j ]\n", - " [0.02-0.01j 0. +0.01j 0. -0.j 0. +0.j ]]\n" - ] - } - ], - "source": [ - "num_qubits = 2\n", - "shadow_size = 10000\n", - "rho_1 = (\n", - " (\n", - " qutip.tensor([qutip.basis(2, 0), qutip.basis(2, 0)])\n", - " + qutip.tensor([qutip.basis(2, 0), qutip.basis(2, 1)])\n", - " )\n", - " .proj()\n", - " .unit()\n", - ")\n", - "print(\"Original density matrix :\")\n", - "print(rho_1.full())\n", - "outcomes, unitary_ids = calculate_classical_shadow(rho_1, shadow_size)\n", - "snapshots = [\n", - " snapshot_state(outcomes[ns], unitary_ids[ns]) for ns in range(shadow_size)\n", - "]\n", - "print(\"Shadow reconstruction :\")\n", - "print(np.around(state_reconstruction(snapshots).full(), 2))\n", - "\n", - "dist = np.zeros(5)\n", - "shadow_sizes = [100, 1000, 2000, 5000, 10000]\n", - "for i, shadow_size in enumerate(shadow_sizes):\n", - " outcomes, unitary_ids = calculate_classical_shadow(rho_1, shadow_size)\n", - " snapshots = [\n", - " snapshot_state(outcomes[ns], unitary_ids[ns])\n", - " for ns in range(shadow_size)\n", - " ]\n", - " dist[i] = qutip.tracedist(state_reconstruction(snapshots), rho_1)\n", - "num_qubits = 4" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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552aMGHCcfeDe+0/77//vkaOHKnrr79e8fHxGj58uF5++WXv+zt37lRxcbHPfYqKilJmZqbPvY6OjtbIkSO9bbKysmQ2m7Vq1Spvm8suu0w2m83bJjs7W5s3b9bhw4c7+jKDwsUXX6y8vDxt2bJFkvTtt9/qiy++0FVXXSWJe91ROvO++vO/KQSjTlRWVqbm5mafXxiSlJCQoOLi4gD1qmtxuVyaPXu2LrnkEp1//vmSpOLiYtlsNkVHR/u0Pfq+FhcXt3rfPe+dqE1lZaXq6uo64nKC0rJly/TNN99owYIFx73HvfafHTt26MUXX9TgwYP14YcfatasWbrnnnu0dOlSSS336kT/vSguLlZ8fLzP+1arVbGxse3699HdPfzww5o6daqGDBmikJAQDR8+XLNnz9b06dMlca87Smfe17banM59t7b7E0AA3XnnndqwYYO++OKLQHelW9q9e7fuvfdeffTRR3I4HIHuTrfmcrk0cuRI/eu//qskafjw4dqwYYOWLFmiG264IcC9617efvttvfHGG3rzzTd13nnnqbCwULNnz1ZSUhL3GsehYtSJ4uLiZLFYjlvBU1JSosTExAD1quu466679Ne//lWffPKJ+vfv7z2emJgop9Op8vJyn/ZH39fExMRW77vnvRO1iYyMVGhoqL8vJyitXbtWpaWluvDCC2W1WmW1WvXpp5/q+eefl9VqVUJCAvfaT/r27atzzz3X59g555yjoqIiSS336kT/vUhMTFRpaanP+01NTTp06FC7/n10dw888IC3anTBBRfoV7/6lX7zm994q6Lc647Rmfe1rTanc98JRp3IZrNpxIgRysvL8x5zuVzKy8vT6NGjA9iz4GYYhu666y699957+vjjjzVo0CCf90eMGKGQkBCf+7p582YVFRV57+vo0aP13Xff+fwF/OijjxQZGen95TR69Gifc3ja9KR/N5dffrm+++47FRYWel8jR47U9OnTvX/mXvvHJZdcctxjJ7Zs2aKBAwdKkgYNGqTExESf+1RZWalVq1b53Ovy8nKtXbvW2+bjjz+Wy+VSZmamt81nn32mxsZGb5uPPvpIZ599tmJiYjrs+oJJbW2tzGbfX3cWi0Uul0sS97qjdOZ99et/U9o9XRtnZNmyZYbdbjdyc3ONjRs3GrfeeqsRHR3ts4IHvmbNmmVERUUZ+fn5xv79+72v2tpab5vbb7/dGDBggPHxxx8bX3/9tTF69Ghj9OjR3vc9S8ivuOIKo7Cw0FixYoXRp0+fVpeQP/DAA8amTZuMxYsX97gl5K05elWaYXCv/WX16tWG1Wo1nnjiCWPr1q3GG2+8YYSFhRmvv/66t83ChQuN6Oho43/+53+M9evXG1dffXWrS52HDx9urFq1yvjiiy+MwYMH+yx1Li8vNxISEoxf/epXxoYNG4xly5YZYWFh3XoJ+bFuuOEGo1+/ft7l+u+++64RFxdnPPjgg9423OvTU1VVZaxbt85Yt26dIcl49tlnjXXr1hn//Oc/DcPovPu6cuVKw2q1Gk8//bSxadMmY/78+SzX70r++Mc/GgMGDDBsNpsxatQo46uvvgp0l4KapFZfr776qrdNXV2dcccddxgxMTFGWFiYcc011xj79+/3Oc+uXbuMq666yggNDTXi4uKM++67z2hsbPRp88knnxgZGRmGzWYzUlNTfb6jpzo2GHGv/ed///d/jfPPP9+w2+3GkCFDjJdeesnnfZfLZcydO9dISEgw7Ha7cfnllxubN2/2aXPw4EFj2rRpRnh4uBEZGWnMnDnTqKqq8mnz7bffGmPGjDHsdrvRr18/Y+HChR1+bcGksrLSuPfee40BAwYYDofDSE1NNX7729/6LP/mXp+eTz75pNX/Pt9www2GYXTufX377beNs846y7DZbMZ5551n/N///d9pXZPJMI569CcAAEAPxhwjAAAAN4IRAACAG8EIAADAjWAEAADgRjACAABwIxgBAAC4EYwAAADcCEYAAABuBCMAQcFkMmn58uV+P++NN96oiRMn+v28pyM3N1fR0dGB7gaAEyAYAehwBw4c0KxZszRgwADZ7XYlJiYqOztbK1euDHTXOtWUKVO0ZcuWQHcDwAlYA90BAN3ftddeK6fTqaVLlyo1NVUlJSXKy8vTwYMHA921ThUaGqrQ0NBAdwPACVAxAtChysvL9fnnn+vJJ5/Uj3/8Yw0cOFCjRo3SnDlz9Itf/MKnbVlZma655hqFhYVp8ODBev/9973vNTc366abbtKgQYMUGhqqs88+W3/4wx98Pt/c3KycnBxFR0erd+/eevDBB3XsdpANDQ265557FB8fL4fDoTFjxmjNmjXe90eOHKmnn37a+/PEiRMVEhKi6upqSdKePXtkMpm0bdu2Vq/322+/1Y9//GNFREQoMjJSI0aM0Ndffy3p+KG0lJQUmUym414eu3fv1uTJkxUdHa3Y2FhdffXV2rVr1yncdQCni2AEoEOFh4crPDxcy5cvV0NDwwnbPvbYY5o8ebLWr1+v8ePHa/r06Tp06JAkyeVyqX///nrnnXe0ceNGzZs3T4888ojefvtt7+efeeYZ5ebm6pVXXtEXX3yhQ4cO6b333vP5jgcffFD//d//raVLl+qbb75Renq6srOzvd8zduxY5efnS5IMw9Dnn3+u6OhoffHFF5KkTz/9VP369VN6enqr1zB9+nT1799fa9as0dq1a/Xwww8rJCSk1bZr1qzR/v37tX//fu3Zs0c/+tGPdOmll0qSGhsblZ2drYiICH3++edauXKlwsPDdeWVV8rpdJ7krgM4bQYAdLD/+q//MmJiYgyHw2FcfPHFxpw5c4xvv/3Wp40k43e/+5335+rqakOS8be//a3N8955553Gtdde6/25b9++xqJFi7w/NzY2Gv379zeuvvpq7zlDQkKMN954w9vG6XQaSUlJ3s+9//77RlRUlNHU1GQUFhYaiYmJxr333ms89NBDhmEYxs0332z88pe/bLNPERERRm5ubqvvvfrqq0ZUVFSr791zzz3GwIEDjdLSUsMwDOO1114zzj77bMPlcnnbNDQ0GKGhocaHH37Y5vcDODNUjAB0uGuvvVb79u3T+++/ryuvvFL5+fm68MILlZub69Nu6NCh3j/36tVLkZGRKi0t9R5bvHixRowYoT59+ig8PFwvvfSSioqKJEkVFRXav3+/MjMzve2tVqtGjhzp/Xn79u1qbGzUJZdc4j0WEhKiUaNGadOmTZKkSy+9VFVVVVq3bp0+/fRTjR07VuPGjfNWkT799FONGzeuzWvNycnRzTffrKysLC1cuFDbt28/6f156aWX9J//+Z96//331adPH0lHhuS2bdumiIgIb9UtNjZW9fX1p3ROAKeHYASgUzgcDv30pz/V3Llz9eWXX+rGG2/U/PnzfdocO+RkMpnkcrkkScuWLdP999+vm266SX//+99VWFiomTNn+n1YKTo6WsOGDVN+fr43BF122WVat26dtmzZoq1bt2rs2LFtfv7RRx/V999/rwkTJujjjz/Wueeee9xw3tE++eQT3X333frzn//sEwyrq6s1YsQIFRYW+ry2bNmiX/7yl369ZgAtCEYAAuLcc89VTU3NKbdfuXKlLr74Yt1xxx0aPny40tPTfSonUVFR6tu3r1atWuU91tTUpLVr13p/TktLk81m83lMQGNjo9asWaNzzz3Xe2zs2LH65JNP9Nlnn2ncuHGKjY3VOeecoyeeeEJ9+/bVWWeddcK+nnXWWfrNb36jv//975o0aZJeffXVVttt27ZN1113nR555BFNmjTJ570LL7xQW7duVXx8vNLT031eUVFRp3bTALQbwQhAhzp48KB+8pOf6PXXX9f69eu1c+dOvfPOO1q0aJGuvvrqUz7P4MGD9fXXX+vDDz/Uli1bNHfuXJ/VZJJ07733auHChVq+fLl++OEH3XHHHSovL/e+36tXL82aNUsPPPCAVqxYoY0bN+qWW25RbW2tbrrpJm+7cePG6cMPP5TVatWQIUO8x954440TVovq6up01113KT8/X//85z+1cuVKrVmzRuecc06rbX/+859r+PDhuvXWW1VcXOx9SUcmccfFxenqq6/W559/rp07dyo/P1/33HOP9uzZc8r3DUD78BwjAB0qPDxcmZmZ+rd/+zfvHJ/k5GTdcssteuSRR075PLfddpvWrVunKVOmyGQyadq0abrjjjv0t7/9zdvmvvvu0/79+3XDDTfIbDbr17/+ta655hpVVFR42yxcuFAul0u/+tWvVFVVpZEjR+rDDz9UTEyMt82ll14ql8vlE4LGjRunP/zhDyecX2SxWHTw4EHNmDFDJSUliouL06RJk/TYY48d17akpEQ//PCDfvjhByUlJfm8ZxiGwsLC9Nlnn+mhhx7SpEmTVFVVpX79+unyyy9XZGTkKd83AO1jMoxjHvIBAADQQzGUBgAA4EYwAgAAcCMYAQAAuBGMAAAA3AhGAAAAbgQjAAAAN4IRAACAG8EIAADAjWAEAADgRjACAABwIxgBAAC4/X88cMZysMKyMAAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(shadow_sizes, dist)\n", - "plt.xlabel(\"Shadow size\")\n", - "plt.ylabel(r\"$||\\rho - \\hat{\\rho}||_1$\")\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can expect, the estimation gets better and better as shadow size gets larger, with about $2$% accuracy at $10000$ shadows. This mostly serves as a reality check, as we will be using classical shadows to estimate observables acting on quantum states, not to reconstruct those states." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Derandomized Paulis" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Derandomization Algorithm" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Randomized classical shadows are useful when dealing with low-weight, general observables. However, suppose, as is the case when estimating the Hamiltonian of the $H_2$ molecule written as a sum of Pauli strings, that we're dealing with Pauli observables of varying weights. In this setting, choosing wisely each Pauli measurement instead of randomly drawing a basis is particularly useful : indeed, say one wants to measure observable $\\sigma_x^1 \\otimes \\sigma_x^2 \\otimes \\dots \\otimes \\sigma_x^n$. Using random rotations in each Pauli $X,Y$ or $Z$ basis and projection in the $Z$ (computational) basis, there is a probability $\\frac{1}{3^n}$ to get each measurement basis right (i.e. rotate the system using the Hadamard matrix). This is extremely unlikely and unefficient as the number of qubits goes up. [Huang et al](https://arxiv.org/abs/2103.07510) outline an interesting greedy algorithm used for choosing suitable measurement bases for the efficient estimation of $L$ $n-$qubit Pauli strings, $\\{O_i\\}$. \n", - "\n", - "Feeding these observables and chosen Pauli measurements {P_i} as input, the algorithm aims at optimizing a certain cost function. This function, labeled $Conf_\\epsilon(O_i, P_j)$ is such that, if $Conf_\\epsilon(O_i, P_j) \\leq \\frac{\\delta}{2}$, then the empirical averages $\\tilde{\\omega_l}$ of each Pauli observable $O_l$ will be $\\epsilon$-close to its true average $Tr(\\rho O_l)$ with probability $1-\\delta$." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In order to implement this cost function, we first need to design two auxiliary functions. The first one decides if a given Pauli measurement $p$ is compatible with (\"hits\") a Pauli observable $o$. This means that each time $o$ acts non-trivially on a qubit $q_i$ with Pauli matrix $\\sigma \\in \\{\\sigma_X, \\sigma_Y, \\sigma_Z\\}, \\sigma \\neq \\mathbb{1}$, $p$ acts on $q_i$ with $\\sigma$. We denote it by $o \\triangleright p$." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "def hits(p, o, end=-1):\n", - " \"\"\"Determines if measurement p hits observable o\n", - "\n", - " Args:\n", - " p (str): Pauli string in str format (ex \"XYZ\"), measurement\n", - " o (str): same as above, observable (ex \"11ZY\")\n", - " end (int): index before which to check if p hits o\n", - " \"\"\"\n", - " if end != -1:\n", - " o = o[:end]\n", - " for i, x in enumerate(o):\n", - " if not (x == p[i] or x == \"1\"):\n", - " return False\n", - " return True" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The second function simply computes the number of qubits observable $o$ acts non-trivially upon." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [], - "source": [ - "def weight(o, start=0):\n", - " o_k = o[start:]\n", - " return len(o_k) - o_k.count(\"1\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now implement the conditioned cost function using these auxiliary functions. We call it \"conditioned\", since we feed it only the first $m \\times n + k$ single-qubit Pauli measurements, and average over the others, not yet determined ones." - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "def cond_conf(o, P_sharp):\n", - " \"\"\"Returns the (modified) conditionned expectation value of the cost function depending\n", - " on already chosen Paulis in P_sharp.\n", - "\n", - " Args:\n", - " o (list[str]): list of Pauli strings to be measured\n", - " P_sharp (list[str]): list of already chosen Paulis\n", - " \"\"\"\n", - " # Hyperparameters : see Huang et al. for more details\n", - " eta = 0.9\n", - " nu = 1 - np.exp(-eta / 2)\n", - " L = len(o)\n", - " m = len(P_sharp) - 1 # index of last chosen Pauli string\n", - " k = (\n", - " len(P_sharp[-1]) - 1\n", - " ) # index of last chosen Pauli matrix in mth Pauli string\n", - " result = 0\n", - " for l in range(0, L):\n", - " v = 0\n", - " for m_prime in range(0, m):\n", - " v += (eta / 2) * int(hits(P_sharp[m_prime], o[l]))\n", - " v -= np.log(\n", - " 1\n", - " - (nu / 3 ** (weight(o[l], start=k + 1)))\n", - " * hits(P_sharp[m], o[l], end=k + 1)\n", - " )\n", - " result += np.exp(-v)\n", - " return result" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we design a simple greedy algorithm which purpose is to minimize this conditioned cost function, choosing one single-qubit Pauli at a time." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [], - "source": [ - "def derandomization(M, o):\n", - " \"\"\"Derandomization algorithm returning best Pauli indices according to a greedy algorithm\n", - " that aims at minimizing the cost function above.\n", - "\n", - " Args:\n", - " M (int): number of measurements\n", - " n (int): number of qubits (size of Pauli strings)\n", - " epsilon (float): desired accuracy on observable expectation values\n", - " o (list[str]): list of Pauli strings to be measured\n", - " \"\"\"\n", - " n = len(o[0])\n", - " P_sharp = []\n", - " for m in range(M):\n", - " P_sharp.append(\"\")\n", - " for k in range(n):\n", - " P_sharp_m = P_sharp[m]\n", - " P_sharp[m] += \"X\"\n", - " valmin = cond_conf(o, P_sharp)\n", - " argmin = \"X\"\n", - " for W in [\"Y\", \"Z\"]:\n", - " P_sharp[m] = P_sharp_m + W\n", - " val_W = cond_conf(o, P_sharp)\n", - " if val_W < valmin:\n", - " valmin = val_W\n", - " argmin = W\n", - " P_sharp[m] = P_sharp_m + argmin\n", - " return P_sharp" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Estimating expectation values from Pauli measurements" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now that we have our Pauli measurements, we proceed differently from randomized classical shadows, where we gave an estimate of the actual quantum channels. Here, we're only interested in the Pauli averages $\\tilde{\\omega}_l$, that we can infer from Pauli measurements $p$ that **hit** observable $o_l$. Indeed, we have the following formula :\n", - "\n", - "$$\\tilde{\\omega}_{l}=\\frac{1}{h\\left(\\mathbf{o}_{l} ;\\left[\\mathbf{p}_{1}, \\ldots, \\mathbf{p}_{M}\\right]\\right)} \\sum_{m: \\mathbf{o}_{l} \\triangleright \\mathbf{p}_{m}} \\prod_{j: \\mathbf{o}_{l}[j] \\neq I} \\mathbf{q}_{m}[j]$$\n", - "\n", - "where $h\\left(\\mathbf{o}_{l} ;\\left[\\mathbf{p}_{1}, \\ldots, \\mathbf{p}_{M}\\right]\\right)$ is the number of times a Pauli measurement $p_i$ is such that $o \\triangleright p_i$, and $\\mathbf{q}_m$ is the output of the measurement of Pauli string $p_m$ ($\\mathbf{q}_m \\in \\{\\pm 1\\}^n$)." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "def _pauli_index(letter):\n", - " if letter == \"X\":\n", - " return 0\n", - " elif letter == \"Y\":\n", - " return 1\n", - " else:\n", - " return 2" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "def pauli_string_value(x, sigma):\n", - " \"\"\"Returns the evaluation of a Pauli string sigma in a bitstring state $|x>$,\n", - " assuming the state is already rotated in the needed eigenbases of all single-qubit Paulis.\n", - "\n", - " NB : Faster than using qutip.measure due to not returning the eigenstates...\n", - "\n", - " Args:\n", - " x (str): input bitstring\n", - " sigma (str): input Pauli string to be measured on |x>\n", - " \"\"\"\n", - " outcomes = []\n", - " for i, q in enumerate(x):\n", - " if q == \"0\":\n", - " outcomes.append((sigma[i], 1))\n", - " else:\n", - " outcomes.append((sigma[i], -1))\n", - " return outcomes" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "def classical_shadow_derand(rho, measurements):\n", - " \"\"\"Returns the n-strings of ±1 corresponding to measurements in the input list on state rho.\n", - "\n", - " Args:\n", - " rho (qutip.Qobj): input state as a density matrix\n", - " measurements (list[str]): derandomized measurement bases in which to measure state rho\n", - "\n", - " Returns:\n", - " Tuple of two numpy arrays. The first array contains measurement outcomes as bitstrings\n", - " while the second array contains the index for the derandomized Pauli's (0,1,2=X,Y,Z).\n", - " \"\"\"\n", - " # Fill the unitary ids with derandomized measurements ids\n", - " shadow_size = len(measurements)\n", - " outcomes = []\n", - " for ns in range(shadow_size):\n", - " # multi-qubit change of basis\n", - " unitmat = qutip.tensor(\n", - " [\n", - " unitary_ensemble[_pauli_index(measurements[ns][i])]\n", - " for i in range(num_qubits)\n", - " ]\n", - " )\n", - " x = measure_bitstring(unitmat.dag() * rho * unitmat)\n", - " outcomes.append(pauli_string_value(x, measurements[ns]))\n", - " # ±1 strings\n", - " return outcomes" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "def exp_value(input_pauli, pm_strings):\n", - " \"\"\"Computes an estimation of the expectation value of a given Pauli string given multiple ±1 bitstring\n", - " outcomes.\n", - " \"\"\"\n", - " sum_product, cnt_match = 0, 0\n", - "\n", - " for single_measurement in pm_strings:\n", - " not_match = False\n", - " product = 1\n", - "\n", - " for i, pauli in enumerate(input_pauli):\n", - " if pauli != single_measurement[i][0] and pauli != \"1\":\n", - " not_match = True\n", - " break\n", - " if pauli != \"1\":\n", - " product *= single_measurement[i][1]\n", - " if not_match:\n", - " continue\n", - "\n", - " sum_product += product\n", - " cnt_match += 1\n", - " if cnt_match == 0:\n", - " return f\"No measurement given for {input_pauli}\"\n", - " return sum_product / cnt_match" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Variational Quantum Simulation for the $H_2$ molecule" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The main problem with usual variational classical algorithms, the classical counterparts of VQS, is computing the value of the $2^n \\times 2^n$ matrix on the output state vector $\\bra{\\psi}H\\ket{\\psi}$ after each loop of the algorithm, which grows exponentially in the size of the system. The purpose of VQS algorithms is to offer a solution which time complexity only grows polynomially, thanks to reading all the important properties on the quantum state. Therefore, we need accurate and efficient methods to estimate these properties, which we'll present afterwards.\n", - "\n", - "For now, let's focus on what makes a VQS algorithm, specifically for computing the groundstate energy of the $H_2$ molecule." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Jordan-Wigner Hamiltonian (cost function)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We need to write the Hamiltonian in a way that's compatible with the formalism of quantum computing. We first second-quantize the Hamiltonian, obtaining an expression in terms of fermionic operators $a, a^\\dagger$. Then, we use the Jordan-Wigner transformation, which maps the fermionic operators to Pauli matrices. We obtain the Hamiltonian below, acting on $4$ qubits, decomposed in terms of the coefficients in front of the Pauli matrices.\n", - "\n", - "[This article by Seeley et al.](https://math.berkeley.edu/~linlin/2018Spring_290/SRL12.pdf) gives us the value of \n", - "$H_{JW}$." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "$$H_{J W}=-0.81261 \\mathbb{1}+0.171201 \\sigma_{0}^{z}+0.171201 \\sigma_{1}^{z}-0.2227965 \\sigma_{2}^{z} \\\\\n", - "-0.2227965 \\sigma_{3}^{z} +0.16862325 \\sigma_{1}^{z} \\sigma_{0}^{z}+0.12054625 \\sigma_{2}^{z} \\sigma_{0}^{z} \\\\\n", - "+0.165868 \\sigma_{2}^{z} \\sigma_{1}^{z}+0.165868 \\sigma_{3}^{z} \\sigma_{0}^{z} +0.12054625 \\sigma_{3}^{z}\\sigma_{1}^{z} \\\\\n", - "+0.17434925 \\sigma_{3}^{z} \\sigma_{2}^{z}-0.04532175 \\sigma_{3}^{x} \\sigma_{2}^{x} \\sigma_{1}^{y} \\sigma_{0}^{y}\\\\\n", - "+0.04532175 \\sigma_{3}^{x} \\sigma_{2}^{y} \\sigma_{1}^{y} \\sigma_{0}^{x}+0.04532175 \\sigma_{3}^{y} \\sigma_{2}^{x}\n", - "\\sigma_{1}^{x} \\sigma_{0}^{y} -0.04532175 \\sigma_{3}^{y} \\sigma_{2}^{y} \\sigma_{1}^{x} \\sigma_{0}^{x}$$" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "def pauli(positions=[], operators=[]):\n", - " op_list = [\n", - " operators[positions.index(j)] if j in positions else qutip.qeye(2)\n", - " for j in range(num_qubits)\n", - " ]\n", - " return qutip.tensor(op_list)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [], - "source": [ - "coeff_fact = [\n", - " 0.81261,\n", - " 0.171201,\n", - " 0.2227965,\n", - " 0.16862325,\n", - " 0.174349,\n", - " 0.12054625,\n", - " 0.165868,\n", - " 0.04532175,\n", - "]\n", - "\n", - "paulis = [\n", - " pauli(),\n", - " pauli([0], [sz]) + pauli([1], [sz]),\n", - " pauli([2], [sz]) + pauli([3], [sz]),\n", - " pauli([1, 0], [sz, sz]),\n", - " pauli([3, 2], [sz, sz]),\n", - " pauli([2, 0], [sz, sz]) + pauli([3, 1], [sz, sz]),\n", - " pauli([2, 1], [sz, sz]) + pauli([3, 0], [sz, sz]),\n", - " pauli([3, 2, 1, 0], [sx, sx, sy, sy])\n", - " + pauli([3, 2, 1, 0], [sy, sy, sx, sx]),\n", - " pauli([3, 2, 1, 0], [sx, sy, sy, sx])\n", - " + pauli([3, 2, 1, 0], [sy, sx, sx, sy]),\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# H2 Molecule : 4 qubits in Jordan-Wigner mapping of the Hamiltonian\n", - "a = 10\n", - "reg = Register.from_coordinates(\n", - " [\n", - " [0, 0],\n", - " [a, 0],\n", - " [0.5 * a, a * np.sqrt(3) / 2],\n", - " [0.5 * a, -a * np.sqrt(3) / 2],\n", - " ]\n", - ")\n", - "reg.draw()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us keep the exact ground-state energy of the molecule for future reference, by diagonalizing it exactly - this is possible for such a small system, however, this quickly becomes an intractable problem for large molecules." - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-1.8510459284448646\n" - ] - } - ], - "source": [ - "def cost_hamiltonian_JW():\n", - " H = (\n", - " -coeff_fact[0] * paulis[0]\n", - " + coeff_fact[1] * paulis[1]\n", - " - coeff_fact[2] * paulis[2]\n", - " + coeff_fact[3] * paulis[3]\n", - " + coeff_fact[4] * paulis[4]\n", - " + coeff_fact[5] * paulis[5]\n", - " + coeff_fact[6] * paulis[6]\n", - " - coeff_fact[7] * paulis[7]\n", - " + coeff_fact[7] * paulis[8]\n", - " )\n", - " return H\n", - "\n", - "\n", - "global H\n", - "H = cost_hamiltonian_JW()\n", - "exact_energy, ground_state = cost_hamiltonian_JW().groundstate()\n", - "print(exact_energy)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Quantum Loop (VQS)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Much like in the *Using QAOA to solve a QUBO problem* notebook, we will use a mixed classical-quantum approach for minimizing the energy. The quantum part will do the exploration in Hilbert space, according to a certain set of parameters $\\theta_i, \\tau_j$, and the classical part will find the optimal parameters given the value of the energy after each loop. For now, we will ignore sampling problems and simply compute the exact expectation value of $H_{JW}$. See [this article by Xiao Yuan et al.](https://arxiv.org/abs/1812.08767) for details about VQS algorithms." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Two mixing Hamiltonians are used for the exploration of the solution space :\n", - "$H_1 = \\hbar / 2 \\sum_i \\sigma_i^x + \\sum_{j" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAi8AAAGdCAYAAADaPpOnAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAwB0lEQVR4nO3df3QV9Z3/8ddNQkIgyQ0kgRADgRAh/BZ/saBFFMqPZVdFD7XKEbEKK2KtSjkS94hiy8bKqm2tq90umljX6tqKolgVERAVEJGIqAkQkUsggIK5N0HIz8/3D7+5xzS/7oQ7mXtvno9z5jR35jNz39MhmZef+cyMyxhjBAAAECainC4AAADACsILAAAIK4QXAAAQVggvAAAgrBBeAABAWCG8AACAsEJ4AQAAYYXwAgAAwkqM0wUEW0NDgw4fPqzExES5XC6nywEAAAEwxqiyslIZGRmKimq7byXiwsvhw4fVv39/p8sAAAAdcPDgQWVmZrbZJuLCS2JioqTvdz4pKcnhagAAQCB8Pp/69+/vP4+3JeLCS+OloqSkJMILAABhJpAhHwzYBQAAYYXwAgAAwgrhBQAAhBXCCwAACCuEFwAAEFYILwAAIKwQXgAAQFghvAAAgLBCeAEAAGGF8AIAAMIK4QUAAIQVwgsAAAgrhJcA1dTU6K677tJtt92m6upqp8sBAKDLchljjNNFBJPP55Pb7ZbX6w3qW6Wrq6vVvXt3SVJFRYXcbnfQtg0AQFdn5fxNz0uAunXr5v+5pqbGwUoAAOjaCC8BioqKUkxMjCTCCwAATiK8WBAbGytJqq2tdbgSAAC6LsKLBY3hhZ4XAACcQ3ixgPACAIDzCC8WNA7aJbwAAOAcwosF9LwAAOA8wosFDNgFAMB5hBcL6HkBAMB5hBcLCC8AADiP8GIBA3YBAHAe4cUCel4AAHAe4cUCBuwCAOA8wosF9LwAAOA8wosFhBcAAJxHeLGAAbsAADiP8GIBPS8AADiP8GIB4QUAAOcRXizgbiMAAJxHeLGAnhcAAJxHeLGA8AIAgPMILxZwtxEAAM4jvFhAzwsAAM4jvFjAgF0AAJxHeLGAnhcAAJxHeLGA8AIAgPMILxYwYBcAAOcRXiyg5wUAAOcRXiwgvAAA4DzCiwXcbQQAgPMILxbQ8wIAgPNsDS8rVqzQhAkT1KNHDyUnJwe0zv3336/c3Fz17NlTvXr10pQpU7Rt2zY7ywwY4QUAAOfZGl5qamo0e/ZsLVy4MOB1hgwZoj/84Q/69NNP9d5772ngwIGaOnWqvv76axsrDQx3GwEA4LwYOze+fPlySVJBQUHA61x33XVNPj/yyCNatWqVdu3apcmTJwezPMvoeQEAwHm2hpczVVNTo//+7/+W2+3WmDFjWmxTXV2t6upq/2efz2dbPQzYBQDAeSE5YPe1115TQkKCunfvrkcffVTr1q1Tampqi23z8/Pldrv9U//+/W2ri54XAACcZzm8LF26VC6Xq82puLj4jIq69NJLVVRUpA8++EDTp0/XT37yEx07dqzFtnl5efJ6vf7p4MGDZ/TdbSG8AADgPMuXjRYvXqx58+a12SY7O7uj9UiSevbsqZycHOXk5Oif/umfdPbZZ2vVqlXKy8tr1jYuLk5xcXFn9H2BYsAuAADOsxxe0tLSlJaWZkctrWpoaGgyrsUp9LwAAOA8W8e8eDweFRUVyePxqL6+XkVFRSoqKlJVVZW/TW5urlavXi1JOnnypO655x5t3bpVBw4c0I4dO/Szn/1Mhw4d0uzZs+0sNSAM2AUAwHm23m20bNkyFRYW+j+PHTtWkrRhwwZNmjRJklRSUiKv1ytJio6OVnFxsQoLC/XNN98oJSVFF1xwgTZv3qwRI0bYWWpA6HkBAMB5LmOMcbqIYPL5fHK73fJ6vUpKSgrqtk+cOKGUlBRJUl1dnaKjo4O6fQAAuior5++QvFU6VDX2vEj0vgAA4BTCiwWNdxtJhBcAAJxCeLGA8AIAgPMILxZERUUpJub7Mc7ccQQAgDMILxZxxxEAAM4ivFhEeAEAwFmEF4t4RQAAAM4ivFhEzwsAAM4ivFjEKwIAAHAW4cUiel4AAHAW4cUiwgsAAM4ivFjEgF0AAJxFeLGInhcAAJxFeLGI8AIAgLMILxZxtxEAAM4ivFhEzwsAAM4ivFhEeAEAwFmEF4u42wgAAGcRXiyi5wUAAGcRXixiwC4AAM4ivFhEzwsAAM4ivFhEeAEAwFmEF4sYsAsAgLMILxbR8wIAgLMILxYxYBcAAGcRXiyi5wUAAGcRXiwivAAA4CzCi0WEFwAAnEV4sYi7jQAAcBbhxSJ6XgAAcBbhxSLuNgIAwFmEF4voeQEAwFmEF4sILwAAOIvwYhEDdgEAcBbhxSJ6XgAAcBbhxSIG7AIA4CzCi0X0vAAA4CzCi0WEFwAAnEV4sYgBuwAAOIvwYhE9LwAAOIvwYhHhBQAAZxFeLOJuIwAAnEV4sYieFwAAnEV4sagxvDQ0NKi+vt7hagAA6HoILxY13m0k0fsCAIATbA0vK1as0IQJE9SjRw8lJydbXv+WW26Ry+XSb3/726DX1lGNPS8S4QUAACfYGl5qamo0e/ZsLVy40PK6q1ev1tatW5WRkWFDZR33w54XBu0CAND5Yuzc+PLlyyVJBQUFltY7dOiQfv7zn+vNN9/UzJkzbais46KiohQTE6O6ujp6XgAAcICt4aUjGhoadP3112vJkiUaMWJEu+2rq6tVXV3t/+zz+ewsT9L3l44ILwAAOCPkBuz+5je/UUxMjG6//faA2ufn58vtdvun/v3721whrwgAAMBJlsPL0qVL5XK52pyKi4s7VMyOHTv0u9/9TgUFBXK5XAGtk5eXJ6/X658OHjzYoe+2gme9AADgHMuXjRYvXqx58+a12SY7O7tDxWzevFnHjh3TgAED/PPq6+u1ePFi/fa3v9VXX33VbJ24uDjFxcV16Ps6iqfsAgDgHMvhJS0tTWlpaXbUouuvv15TpkxpMm/atGm6/vrrdeONN9rynR1BzwsAAM6xdcCux+PRiRMn5PF4VF9fr6KiIklSTk6OEhISJEm5ubnKz8/XrFmzlJKSopSUlCbb6Natm9LT0zV06FA7S7WE8AIAgHNsDS/Lli1TYWGh//PYsWMlSRs2bNCkSZMkSSUlJfJ6vXaWEXSEFwAAnGNreCkoKGj3GS/GmDaXtzTOxWncbQQAgHNC7jkv4aCx52XBggVKTExstvy8885TYWGhoqJC7k50AADCHuGlA4YMGaKtW7eqrKysxeVffPGF8vLyNHz48E6uDACAyEd46YA//elPWrBggerq6potu/nmm7Vv3z4dPHiQ8AIAgA0ILx0QGxuriy66qMVlQ4YM8YcXAAAQfAzKCLLG1xN4PB6HKwEAIDIRXoKsMbzQ8wIAgD0IL0FGeAEAwF6ElyBrfC8T4QUAAHsQXoLsh2Ne2nsAHwAAsI7wEmSZmZmSpNOnT+v48eMOVwMAQOQhvARZXFyc+vTpI4lLRwAA2IHwYgMG7QIAYB/Ciw0YtAsAgH0ILzbgQXUAANiH8GIDLhsBAGAfwosNCC8AANiH8GIDxrwAAGAfwosNGnteysrKVF9f73A1AABEFsKLDfr166fo6GjV19fryJEjTpcDAEBEIbzYIDo6WhkZGZK4dAQAQLARXmzC7dIAANiD8GKTwYMHS5JKSkocrgQAgMhCeLHJOeecI0kqKipytA4AACIN4cUmhBcAAOxBeLHJmDFjJElffvmlfD6fw9UAABA5CC82SUlJUWZmpiRp165dDlcDAEDkILzYiEtHAAAEH+HFRoQXAACCj/BiI8ILAADBR3ixUeOg3d27d6uurs7hagAAiAyEFxtlZ2crISFB1dXVPKwOAIAgIbzYKCoqyt/7wqUjAACCg/BiM8a9AAAQXIQXmzX2vHzyyScOVwIAQGQgvNjshz0vxhhniwEAIAIQXmw2cuRIRUVF6euvv1Z5ebnT5QAAEPYILzaLj4/X0KFDJTHuBQCAYCC8dILGS0eMewEA4MwRXjoBdxwBABA8hJdOQHgBACB4CC+doPF26b179+rkyZMOVwMAQHgjvHSCvn37Kj09XcYYffrpp06XAwBAWCO8dBIuHQEAEByEl05CeAEAIDhsDS8rVqzQhAkT1KNHDyUnJwe0zrx58+RyuZpM06dPt7PMTtE47uWll17SlVde6Z9uvPFGHTlyxOHqAAAIHzF2brympkazZ8/W+PHjtWrVqoDXmz59up5++mn/57i4ODvK61Tjxo3zP2n3lVdeabJs+PDhWrJkiUOVAQAQXmwNL8uXL5ckFRQUWFovLi5O6enpNlTknEGDBmnDhg0qLi72z1uzZo3Wrl2rsrIyBysDACC82BpeOmrjxo3q06ePevXqpcsuu0y//vWvlZKS0mLb6upqVVdX+z/7fL7OKtOyiRMnauLEif7Pp0+f1tq1a3X48GEHqwIAILyE3IDd6dOn65lnntH69ev1m9/8Rps2bdKMGTNUX1/fYvv8/Hy53W7/1L9//06uuOP69esnSbywEQAACyyHl6VLlzYbUPuP0w8vjVj105/+VJdffrlGjRqlK6+8Uq+99pq2b9+ujRs3ttg+Ly9PXq/XPx08eLDD393ZCC8AAFhn+bLR4sWLNW/evDbbZGdnd7SeFreVmpqqffv2afLkyc2Wx8XFhe2A3oyMDEnfhxdjjFwul8MVAQAQ+iyHl7S0NKWlpdlRS4vKysp0/Phxfy9FJGncp1OnTsnn88ntdjtcEQAAoc/WMS8ej0dFRUXyeDyqr69XUVGRioqKVFVV5W+Tm5ur1atXS5Kqqqq0ZMkSbd26VV999ZXWr1+vK664Qjk5OZo2bZqdpToiPj7eH1gYtAsAQGBsvdto2bJlKiws9H8eO3asJGnDhg2aNGmSJKmkpERer1eSFB0drV27dqmwsFAVFRXKyMjQ1KlT9atf/SpsLw21p1+/fvJ6vSovL9ewYcOcLgcAgJBna3gpKCho9xkvxhj/z/Hx8XrzzTftLCnkZGRkqLi4mEG7AAAEKORule5quOMIAABrCC8OawwvjHkBACAwhBeH0fMCAIA1hBeH/fBZLwAAoH2EF4fR8wIAgDWEF4cx5gUAAGsILw5rDC9VVVVNHt4HAABaRnhxWGJionr27CmJS0cAAASC8BICGLQLAEDgCC8hgEG7AAAEjvASAhi0CwBA4AgvIYCeFwAAAkd4CQGMeQEAIHCElxBw1llnSZI8Ho/DlQAAEPoILyFgyJAhkqSSkhKHKwEAIPQRXkJAbm6uJOno0aP69ttvHa4GAIDQRngJAQkJCcrMzJQkFRcXO1wNAAChjfASIhp7XwgvAAC0jfASIggvAAAEhvASIoYNGyZJ+uKLLxyuBACA0EZ4CRH0vAAAEBjCS4hoDC9ffvmlqqurHa4GAIDQRXgJEf369VNSUpLq6+tVWlrqdDkAAIQswkuIcLlc/t4Xxr0AANA6wksIYdwLAADtI7yEEMILAADtI7yEEG6XBgCgfYSXENLY81JSUiJjjMPVAAAQmggvISQrK0uSVFVVJZ/P53A1AACEJsJLCImPj5fb7ZYkHT582OFqAAAITYSXEJORkSFJKi8vd7gSAABCE+ElxPTr108S4QUAgNYQXkJMY3jhshEAAC0jvIQYLhsBANA2wkuI4bIRAABtI7yEGMILAABtI7yEGMa8AADQNsJLiGHMCwAAbSO8hJjGnpeqqipVVlY6XA0AAKGH8BJiEhISlJCQIIneFwAAWkJ4CUEM2gUAoHWElxDEuBcAAFpHeAlB9LwAANA6wksI4nZpAABaR3gJQVw2AgCgdbaFlxUrVmjChAnq0aOHkpOTA17viy++0OWXXy63262ePXvqggsukMfjsavMkMRlIwAAWmdbeKmpqdHs2bO1cOHCgNcpLS3VxRdfrNzcXG3cuFG7du3Svffeq+7du9tVZkjishEAAK2LsWvDy5cvlyQVFBQEvM6///u/65//+Z/10EMP+ecNHjw42KWFPHpeAABoXciMeWloaNDatWs1ZMgQTZs2TX369NG4ceP08ssvt7ledXW1fD5fkyncNY558Xq9OnXqlMPVAAAQWkImvBw7dkxVVVV68MEHNX36dL311luaNWuWrrrqKm3atKnV9fLz8+V2u/1T//79O7FqeyQlJSk+Pl4SvS8AAPwjS+Fl6dKlcrlcbU7FxcUdKqShoUGSdMUVV+jOO+/UOeeco6VLl+pf/uVf9OSTT7a6Xl5enrxer386ePBgh74/lLhcLv+lo0OHDjlcDQAAocXSmJfFixdr3rx5bbbJzs7uUCGpqamKiYnR8OHDm8wfNmyY3nvvvVbXi4uLU1xcXIe+M5T1799fX375pcrKypwuBQCAkGIpvKSlpSktLc2WQmJjY3XBBReopKSkyfw9e/YoKyvLlu8MZQMGDJCkLnebOAAA7bHtbiOPx6MTJ07I4/Govr5eRUVFkqScnBz/W5Nzc3OVn5+vWbNmSZKWLFmia665RhMnTtSll16qN954Q6+++qo2btxoV5khi/ACAEDLbAsvy5YtU2Fhof/z2LFjJUkbNmzQpEmTJEklJSXyer3+NrNmzdKTTz6p/Px83X777Ro6dKj+9re/6eKLL7arzJBFeAEAoGUuY4xxuohg8vl8crvd8nq9SkpKcrqcDnvjjTc0Y8YMjR49Wp988onT5QAAYCsr5++QuVUaTTXe8k3PCwAATRFeQlRjeKmoqFBlZaXD1QAAEDoILyEqKSnJ/0LLSHh2DQAAwUJ4CWEM2gUAoDnCSwgjvAAA0BzhJYQRXgAAaI7wEsIILwAANEd4CWGEFwAAmiO8hDDCCwAAzRFeQljjs17KyspUX1/vcDUAAIQGwksIy8jIUFRUlGpra3X06FGnywEAICQQXkJYTEyMzjrrLElcOgIAoBHhJcQx7gUAgKYILyGuMbzccMMNcrvdrU7p6elau3atw9UCAGA/wkuIu/TSSyVJp0+fls/na3U6evSonnvuOYerBQDAfjFOF4C2zZ8/XzNnztR3333Xapt169bp1ltv1b59+zqxMgAAnEF4CQMZGRltLj958qQkqbS0tDPKAQDAUVw2igDZ2dmSpOPHj6uiosLZYgAAsBnhJQIkJiaqb9++kuh9AQBEPsJLhMjJyZEkxr0AACIe4SVCDB48WBLhBQAQ+QgvEaKx54XLRgCASEd4iRBcNgIAdBWElwjBZSMAQFdBeIkQjT0v5eXl/ue+AAAQiQgvEaJ3797q1auXJOnLL790uBoAAOxDeIkgjZeOGLQLAIhkhJcIwqBdAEBXQHiJIAzaBQB0BYSXCMKzXgAAXQHhJYJw2QgA0BUQXiJI42Ujj8ejmpoah6sBAMAehJcIkp6erh49eqihoUFfffWV0+UAAGALwksEcblcXDoCAEQ8wkuE4VkvAIBIR3iJMPS8AAAiHeElwnC7NAAg0hFeIgwPqgMARDrCS4Rp7Hn58ssvVV9f73A1AAAEH+ElwmRmZio2Nla1tbUqKytzuhwAAIKO8BJhoqOjNWjQIElcOgIARCbCSwTijiMAQCQjvEQgnvUCAIhkhJcIRM8LACCS2RpeVqxYoQkTJqhHjx5KTk4OaB2Xy9XitHLlSjtLjSg86wUAEMli7Nx4TU2NZs+erfHjx2vVqlUBrVNeXt7k89///nfddNNNuvrqq+0oMSL98FkvzzzzTIttJk6cqIEDB3ZiVQAABIfLGGPs/pKCggLdcccdqqiosLzulVdeqcrKSq1fvz6g9j6fT263W16vV0lJSZa/LxLU1NSoZ8+eqqura7XNkCFDVFJS0olVAQDQOivnb1t7Xs7U0aNHtXbtWhUWFrbaprq6WtXV1f7PPp+vM0oLabGxsfr973+vNWvWtLj8jTfe0J49e/TNN98oNTW1k6sDAODMhHR4KSwsVGJioq666qpW2+Tn52v58uWdWFV4WLhwoRYuXNjispycHJWWluqTTz7R5MmTO7kyAADOjOUBu0uXLm11UG3jVFxcHJTinnrqKc2ZM0fdu3dvtU1eXp68Xq9/OnjwYFC+O5KNGTNGkvTJJ584XAkAANZZ7nlZvHix5s2b12ab7Ozsjtbjt3nzZpWUlOiFF15os11cXJzi4uLO+Pu6kjFjxuill14ivAAAwpLl8JKWlqa0tDQ7amli1apVOu+88/y9BAgeel4AAOHM1ue8eDweFRUVyePxqL6+XkVFRSoqKlJVVZW/TW5urlavXt1kPZ/PpxdffFE333yzneV1Weecc44k6fPPP1dNTY2zxQAAYJGtA3aXLVvW5E6hsWPHSpI2bNigSZMmSZJKSkrk9XqbrPf888/LGKNrr73WzvK6rAEDBig5OVkVFRUqLi7W6NGjnS4JAICAdcpzXjoTz3kJzCWXXKJ3331XhYWFmjt3rtPlAAC6OCvnb95t1EUx7gUAEK4IL10U4QUAEK5C+iF1sM8Pw8sPn0ocHR2tnj17OlUWAADtouelixoxYoSioqL0zTffyO12+6eEhATdf//9TpcHAECrCC9dVHx8vK655poWl/3ud7/T6dOnO7kiAAACQ3jpwp577jmdOnXKP508eVJnnXWWKioqtHbtWqfLAwCgRYSXLq579+7+qUePHpozZ44k6c9//rPDlQEA0DLCC5q4/vrrJUmvv/66vvnmG4erAQCgOcILmhg5cqTGjh2r2tradl+KCQCAE7hVGs3MnTtXO3fu1D333KP/+q//OuPtXXjhhXrqqafkcrmCUB0AoKvj9QBo5ujRo8rJyWnyAs0z9dlnn2n48OFB2x4AILJYOX/T84Jm+vbtq88++0ylpaVnvK3bb79du3fvJrwAAIKG8IIWDRgwQAMGDDjj7VxwwQXavXu3du/erdmzZwehMgBAV8eAXdhq5MiRkr6/bAQAQDAQXmCrESNGSCK8AACCh/ACWzX2vOzdu1fV1dUOVwMAiASEF9gqIyNDbrdb9fX1KikpcbocAEAEILzAVi6Xi0tHAICgIrzAdo2Xjnbv3u1wJQCASEB4ge3oeQEABBPhBbbjdmkAQDARXmC7xp6X0tJSnTp1yuFqAADhjifswnZ9+vRRSkqKjh8/rvvuu099+vSxtP7EiRN14YUX2lQdACDcEF5gO5fLpTFjxuidd97RypUrLa+fmJiosrIyXrQJAJBEeEEneeihh/TEE0+otrbW0nrr1q1TeXm5nn/+eS1YsMCm6gAA4cRljDFOFxFMVl6pjdD38MMP65e//KXOP/98bd++3elyAAA2sXL+ZsAuQtoNN9yg2NhYffTRR9q5c6fT5QAAQgDhBSEtNTVVs2bNkiT96U9/crgaAEAoYMwLQt78+fP1wgsvqLCwUHv37u3wdsaPH68HHnggiJUBAJzAmBeEvIaGBo0YMULFxcVnvK39+/dr4MCBZ14UACCorJy/6XlByIuKitK6deu0efNmdTRr33PPPTpw4IBKSkoILwAQ5ggvCAuZmZm69tprO7z+X//6V394mTZtWhArAwB0NgbsoksYOnSoJKmkpMThSgAAZ4rwgi6B8AIAkYPwgi6B8AIAkYPwgi5hyJAhkqSysjKdPHnS4WoAAGeC8IIuISUlRSkpKZKkPXv2OFwNAOBMEF7QZXDpCAAiA+EFXQbhBQAiA+EFXQbhBQAiA+EFXQbhBQAiA+EFXUZjeNmzZ0+HXzMAAHAe4QVdxuDBgxUdHa2qqiodPnzY6XIAAB3Eu43QZcTGxmrQoEHat2+fLrnkEsXHxztaj9vt1nXXXafrr79eiYmJjtYCAOGE8IIu5aKLLtK+fftUWlrqdCmSpPfff19Lly7VmjVrNGnSJKfLAYCw4DI2XfxfsWKF1q5dq6KiIsXGxqqioqLddaqqqrR06VK9/PLLOn78uAYNGqTbb79dt9xyS8Df6/P55Ha75fV6lZSUdAZ7gEhUXV2tbdu2qa6uzulS9Omnn+rxxx/X3r17NXnyZL399ttOlwQAjrFy/rYtvNx3331KTk5WWVmZVq1aFVB4WbBggd555x39z//8jwYOHKi33npLt956q1566SVdfvnlAX0v4QXhpLi4WMOGDVNcXJy+/fZbxy9lAYBTrJy/bRuwu3z5ct15550aNWpUwOt88MEHuuGGGzRp0iQNHDhQCxYs0JgxY/Thhx/aVSbgqKFDhyozM1PV1dXavHmz0+UAQFgIqbuNJkyYoDVr1ujQoUMyxmjDhg3as2ePpk6d2uo61dXV8vl8TSYgXLhcLv34xz+WJK1bt87hagAgPIRUeHnsscc0fPhwZWZmKjY2VtOnT9fjjz+uiRMntrpOfn6+3G63f+rfv38nVgycucbw8tZbbzlcCQCEB0vhZenSpXK5XG1OxcXFHS7mscce09atW7VmzRrt2LFDDz/8sBYtWtTmQMa8vDx5vV7/dPDgwQ5/P+CEyZMnS5J27dqlo0ePOlwNAIQ+SwN2v/76ax0/frzNNtnZ2YqNjfV/Ligo0B133NHugN1Tp07J7XZr9erVmjlzpn/+zTffrLKyMr3xxhsB1ciAXYSjc889Vzt37tSzzz6rOXPmOF0OAHQ6K+dvS895SUtLU1pa2hkV15ra2lrV1tYqKqppZ1B0dLQaGhps+U4gVPz4xz/Wzp079Yc//KHdZ9BMnjxZF110USdVBgChx7aH1Hk8Hp04cUIej0f19fUqKiqSJOXk5CghIUGSlJubq/z8fM2aNUtJSUm65JJLtGTJEsXHxysrK0ubNm3SM888o0ceecSuMoGQMG3aND300EPaunWrtm7d2mbb+++/X48//rgWLlzYSdUBQGix7Tkv8+bNU2FhYbP5GzZs8D9J1OVy6emnn9a8efMkSUeOHFFeXp7eeustnThxQllZWVqwYIHuvPNOuVyugL6Xy0YIR8YYPfzww+32ung8Hr3++uuSvn8u0tlnn91m+9TUVF199dW8fgBAyAuJh9Q5hfCCSGaM0QMPPKD7778/4HXcbrfmz5+vpUuXKiUlxb7iAOAMEF4IL4hwf/vb37RmzRq19+u7bds27dmzR5KUmZmp5557Tj/60Y86o0QAsITwQngBJEkNDQ16/fXXtXjxYu3Zs0dRUVE6//zz5XK5FB8frz59+qhXr15NBsr/4yXaH35u/NnlcmnGjBmaMWNG5+wIgIhHeCG8AE1UVlZq0aJF+vOf/xy0bXbv3l0ej8e2OxABdC2EF8IL0KLt27ervLxcknTy5EkdO3asyTOYfvjnoLWfJenFF19UcXGx7r33Xj3wwAP2Fg2gSyC8EF4AW/31r3/V7Nmz1atXL3k8Hv/jDwCgo0LirdIAItesWbOUk5Ojb7/9VqtWrXK6HABdDD0vADrkj3/8o2655Ralpqbq4osv9s93uVzKysrS6NGjddlllykrK8vBKgGECy4bEV4A250+fVrZ2dn+MTQtiYuL069+9Svdddddio6O7sTqAIQbwgvhBegUe/bs0caNG5vMq6ur0969e/X+++9r+/btkqTBgwcH5a6k9PR0rVy5Ujk5OWe8LQChhfBCeAEcZ4xRQUGB7rzzTnm93qBtNysrS++9954yMzODtk0AziO8EF6AkPH1119ry5Yt7T4NuD0NDQ26++67tXfvXuXm5mrZsmVyuVztTlFRUQG1O9NpwIAB6tu3b5D+XwO6HsIL4QWISAcOHNDFF1+ssrIyp0tpUVZWloYOHdrkicU/NGzYMM2fP1/Dhg3r5MqA0Ed4IbwAEWvPnj2699579fXXX8sYY/vU0NDQbpv6+nodPnw44N6lkSNHKj4+PqC20dHRysnJ0ciRI9W7d+9W2yUmJsrtdisuLq7dbSYkJCg9PV29evWSy+VSTEyMunfvHlA9gF0IL4QXAJ3M5/Np+/btrfYK1dbW6rXXXtOrr76qhoaGTq6ubS6XS+eee66mTp2qjIyMJvN/+L8tzWtrmdV5MTExysjIUGZmpuLj49u99PeP87t37x5QeENoIrwQXgCEqEOHDqmoqCjg9qdPn1ZxcbE+++wznTx5ssU2DQ0NqqqqktfrVW1tbZvbM8bI5/PpyJEj7bYNN1FRURo+fLjOPffcoD31+R9fVMp2vtetWzf953/+Z1BqaUR4IbwAQJuMMTp9+rQk6cSJE1q/fr02btzoD0iNp4aW3nEVyLKObKO6ulqHDh1SWVmZqqurm12+Q+iIi4vz//sJFivn75igfjMAICy4XC7/uJuzzjpLc+fO1dy5cx2uqn1tjUc6fvy4duzYoU8//VQ1NTW2fLdd7Nq2Xdt1+qGT9LwAAADH8WJGAAAQsSL3stHJkxLvUgEAIDy0MiC9JZEbXn5wux8AAIgcXDYCAABhJXJ7Xg4flhiwCwBAePD5Ar5qErnhpWfP7ycAABD66usDbsplIwAAEFYILwAAIKwQXgAAQFghvAAAgLBCeAEAAGGF8AIAAMIK4QUAAISViHvOS+NLsn0+n8OVAACAQDWetxvP422JuPBSWVkpSerfv7/DlQAAAKsqKyvldrvbbOMygUScMNLQ0KDDhw8rMTFRLpcrqNv2+Xzq37+/Dh48qKQIffVApO9jpO+fxD5GgkjfP4l9jATB3j9jjCorK5WRkaGoqLZHtURcz0tUVJQyMzNt/Y6kpKSI/If4Q5G+j5G+fxL7GAkiff8k9jESBHP/2utxacSAXQAAEFYILwAAIKwQXiyIi4vTfffdp7i4OKdLsU2k72Ok75/EPkaCSN8/iX2MBE7uX8QN2AUAAJGNnhcAABBWCC8AACCsEF4AAEBYIbwAAICwQnix4PHHH9fAgQPVvXt3jRs3Th9++KHTJXVIfn6+LrjgAiUmJqpPnz668sorVVJS0qTNpEmT5HK5mky33HKLQxVbd//99zerPzc317/89OnTWrRokVJSUpSQkKCrr75aR48edbBiawYOHNhs/1wulxYtWiQpPI/fu+++q3/9139VRkaGXC6XXn755SbLjTFatmyZ+vXrp/j4eE2ZMkV79+5t0ubEiROaM2eOkpKSlJycrJtuuklVVVWduBdta2sfa2trdffdd2vUqFHq2bOnMjIyNHfuXB0+fLjJNlo69g8++GAn70nL2juG8+bNa1b79OnTm7QJ52MoqcXfS5fLpZUrV/rbhPIxDOT8EMjfT4/Ho5kzZ6pHjx7q06ePlixZorq6uqDVSXgJ0AsvvKC77rpL9913nz7++GONGTNG06ZN07Fjx5wuzbJNmzZp0aJF2rp1q9atW6fa2lpNnTpVJ0+ebNJu/vz5Ki8v908PPfSQQxV3zIgRI5rU/9577/mX3XnnnXr11Vf14osvatOmTTp8+LCuuuoqB6u1Zvv27U32bd26dZKk2bNn+9uE2/E7efKkxowZo8cff7zF5Q899JB+//vf68knn9S2bdvUs2dPTZs2TadPn/a3mTNnjj777DOtW7dOr732mt59910tWLCgs3ahXW3t43fffaePP/5Y9957rz7++GO99NJLKikp0eWXX96s7QMPPNDk2P785z/vjPLb1d4xlKTp06c3qf0vf/lLk+XhfAwlNdm38vJyPfXUU3K5XLr66qubtAvVYxjI+aG9v5/19fWaOXOmampq9MEHH6iwsFAFBQVatmxZ8Ao1CMiFF15oFi1a5P9cX19vMjIyTH5+voNVBcexY8eMJLNp0yb/vEsuucT84he/cK6oM3TfffeZMWPGtLisoqLCdOvWzbz44ov+eV988YWRZLZs2dJJFQbXL37xCzN48GDT0NBgjAn/4yfJrF692v+5oaHBpKenm5UrV/rnVVRUmLi4OPOXv/zFGGPM559/biSZ7du3+9v8/e9/Ny6Xyxw6dKjTag/UP+5jSz788EMjyRw4cMA/Lysryzz66KP2FhcELe3fDTfcYK644opW14nEY3jFFVeYyy67rMm8cDmGxjQ/PwTy9/P11183UVFR5siRI/42TzzxhElKSjLV1dVBqYuelwDU1NRox44dmjJlin9eVFSUpkyZoi1btjhYWXB4vV5JUu/evZvM/9///V+lpqZq5MiRysvL03fffedEeR22d+9eZWRkKDs7W3PmzJHH45Ek7dixQ7W1tU2OZ25urgYMGBCWx7OmpkbPPvusfvaznzV5GWm4H78f2r9/v44cOdLkmLndbo0bN85/zLZs2aLk5GSdf/75/jZTpkxRVFSUtm3b1uk1B4PX65XL5VJycnKT+Q8++KBSUlI0duxYrVy5Mqjd8XbbuHGj+vTpo6FDh2rhwoU6fvy4f1mkHcOjR49q7dq1uummm5otC5dj+I/nh0D+fm7ZskWjRo1S3759/W2mTZsmn8+nzz77LCh1RdyLGe3wzTffqL6+vsmBkKS+ffuquLjYoaqCo6GhQXfccYcuuugijRw50j//uuuuU1ZWljIyMrRr1y7dfffdKikp0UsvveRgtYEbN26cCgoKNHToUJWXl2v58uX60Y9+pN27d+vIkSOKjY1tdkLo27evjhw54kzBZ+Dll19WRUWF5s2b558X7sfvHzUel5Z+BxuXHTlyRH369GmyPCYmRr179w7L43r69Gndfffduvbaa5u89O7222/Xueeeq969e+uDDz5QXl6eysvL9cgjjzhYbWCmT5+uq666SoMGDVJpaanuuecezZgxQ1u2bFF0dHTEHcPCwkIlJiY2uyQdLsewpfNDIH8/jxw50uLvauOyYCC8dHGLFi3S7t27m4wHkdTkGvOoUaPUr18/TZ48WaWlpRo8eHBnl2nZjBkz/D+PHj1a48aNU1ZWlv7v//5P8fHxDlYWfKtWrdKMGTOUkZHhnxfux6+rq62t1U9+8hMZY/TEE080WXbXXXf5fx49erRiY2P1b//2b8rPzw/5x9D/9Kc/9f88atQojR49WoMHD9bGjRs1efJkByuzx1NPPaU5c+aoe/fuTeaHyzFs7fwQCrhsFIDU1FRFR0c3G0199OhRpaenO1TVmbvtttv02muvacOGDcrMzGyz7bhx4yRJ+/bt64zSgi45OVlDhgzRvn37lJ6erpqaGlVUVDRpE47H88CBA3r77bd18803t9ku3I9f43Fp63cwPT292QD6uro6nThxIqyOa2NwOXDggNatW9ek16Ul48aNU11dnb766qvOKTCIsrOzlZqa6v93GSnHUJI2b96skpKSdn83pdA8hq2dHwL5+5ment7i72rjsmAgvAQgNjZW5513ntavX++f19DQoPXr12v8+PEOVtYxxhjddtttWr16td555x0NGjSo3XWKiookSf369bO5OntUVVWptLRU/fr103nnnadu3bo1OZ4lJSXyeDxhdzyffvpp9enTRzNnzmyzXbgfv0GDBik9Pb3JMfP5fNq2bZv/mI0fP14VFRXasWOHv80777yjhoYGf3gLdY3BZe/evXr77beVkpLS7jpFRUWKiopqdrklHJSVlen48eP+f5eRcAwbrVq1Suedd57GjBnTbttQOobtnR8C+fs5fvx4ffrpp02CaGMQHz58eNAKRQCef/55ExcXZwoKCsznn39uFixYYJKTk5uMpg4XCxcuNG6322zcuNGUl5f7p++++84YY8y+ffvMAw88YD766COzf/9+88orr5js7GwzceJEhysP3OLFi83GjRvN/v37zfvvv2+mTJliUlNTzbFjx4wxxtxyyy1mwIAB5p133jEfffSRGT9+vBk/frzDVVtTX19vBgwYYO6+++4m88P1+FVWVpqdO3eanTt3GknmkUceMTt37vTfafPggw+a5ORk88orr5hdu3aZK664wgwaNMicOnXKv43p06ebsWPHmm3btpn33nvPnH322ebaa691apeaaWsfa2pqzOWXX24yMzNNUVFRk9/Nxjs0PvjgA/Poo4+aoqIiU1paap599lmTlpZm5s6d6/Cefa+t/ausrDS//OUvzZYtW8z+/fvN22+/bc4991xz9tlnm9OnT/u3Ec7HsJHX6zU9evQwTzzxRLP1Q/0Ytnd+MKb9v591dXVm5MiRZurUqaaoqMi88cYbJi0tzeTl5QWtTsKLBY899pgZMGCAiY2NNRdeeKHZunWr0yV1iKQWp6efftoYY4zH4zETJ040vXv3NnFxcSYnJ8csWbLEeL1eZwu34JprrjH9+vUzsbGx5qyzzjLXXHON2bdvn3/5qVOnzK233mp69eplevToYWbNmmXKy8sdrNi6N99800gyJSUlTeaH6/HbsGFDi/8ub7jhBmPM97dL33vvvaZv374mLi7OTJ48udm+Hz9+3Fx77bUmISHBJCUlmRtvvNFUVlY6sDcta2sf9+/f3+rv5oYNG4wxxuzYscOMGzfOuN1u0717dzNs2DDzH//xH01O/k5qa/++++47M3XqVJOWlma6detmsrKyzPz585v9B2A4H8NGf/zjH018fLypqKhotn6oH8P2zg/GBPb386uvvjIzZsww8fHxJjU11SxevNjU1tYGrU7X/y8WAAAgLDDmBQAAhBXCCwAACCuEFwAAEFYILwAAIKwQXgAAQFghvAAAgLBCeAEAAGGF8AIAAMIK4QUAAIQVwgsAAAgrhBcAABBWCC8AACCs/D8m/7qANeh5qwAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.plot(\n", - " [quantum_loop(pars, gggg) for pars in loop_ising_results.allvecs], \"k\"\n", - ")\n", - "plt.axhline(exact_energy, color=\"red\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Seems like we can cut on calculation time by only allowing $100$ iterations, since we don't get much more accurate afterwards." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Estimating Jordan-Wigner $H_2$ Hamiltonian with classical shadows" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Randomized measurements" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now consider the real-life problem where we don't have access to the exact value $\\bra{\\Psi(\\theta_i, \\tau_j)} H_{JW} \\ket{\\Psi(\\theta_i, \\tau_j)}$. It can be estimated with classical shadows.\n", - "We modify the quantum loop to add classical shadow estimation of the several Pauli strings making up the $H_{JW}$ Hamiltonian : this is the perfect setting to do so, because we have multiple Pauli strings and most of them have low weight." - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [], - "source": [ - "def exp_value_JW(exp_values):\n", - " return (\n", - " -coeff_fact[0] * exp_values[0]\n", - " + coeff_fact[1] * exp_values[1]\n", - " - coeff_fact[2] * exp_values[2]\n", - " + coeff_fact[3] * exp_values[3]\n", - " + coeff_fact[4] * exp_values[4]\n", - " + coeff_fact[5] * exp_values[5]\n", - " + coeff_fact[6] * exp_values[6]\n", - " - coeff_fact[7] * exp_values[7]\n", - " + coeff_fact[7] * exp_values[8]\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "def quantum_loop_shadows(param, in_state, shadow_size=20, r=reg):\n", - " \"\"\"\n", - " Args:\n", - " param (np.array): time parameters for each mixing Hamiltonian. There are 2p time parameters in param.\n", - " in_state (qubit.Qobj): initial state.\n", - " \"\"\"\n", - " seq = Sequence(r, DigitalAnalogDevice)\n", - " seq.declare_channel(\"ch0\", \"rydberg_global\")\n", - " middle = len(param) // 2\n", - "\n", - " for tau, t in zip(param[middle:], param[:middle]):\n", - " pulse_1 = Pulse.ConstantPulse(tau, 1.0, 0, 0)\n", - " pulse_2 = Pulse.ConstantPulse(t, 1.0, 1.0, 0)\n", - " seq.add(pulse_1, \"ch0\")\n", - " seq.add(pulse_2, \"ch0\")\n", - "\n", - " seq.measure(\"ground-rydberg\")\n", - " simul = QutipEmulator.from_sequence(seq, sampling_rate=0.01)\n", - " simul.set_initial_state(in_state)\n", - "\n", - " # Classical shadow estimation\n", - " # Theoretical shadow size and number of clusters :\n", - " # shadow_size, K = compute_shadow_size(0.1, 0.5, paulis)\n", - " # We use K=4 to allow for quick simulation\n", - " K = 4\n", - " rho = simul.run().get_final_state().proj()\n", - " outcomes, unitary_ids = calculate_classical_shadow(rho, shadow_size)\n", - " snapshots = [\n", - " snapshot_state(outcomes[ns], unitary_ids[ns])\n", - " for ns in range(shadow_size)\n", - " ]\n", - " meds = [_median_of_means(obs, snapshots, K) for obs in paulis]\n", - " return exp_value_JW(meds)\n", - "\n", - "\n", - "def loop_JW_shadows(param, in_state, shadow_size=20):\n", - " res = minimize(\n", - " quantum_loop_shadows,\n", - " param,\n", - " method=\"Nelder-Mead\",\n", - " args=(in_state, shadow_size),\n", - " options={\"return_all\": True, \"maxiter\": 100, \"adaptive\": True},\n", - " )\n", - " return res" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "shadow_sizes = [10, 20, 40, 60, 80, 100]\n", - "energies = []\n", - "for shadow_size in shadow_sizes:\n", - " energies.append(\n", - " abs(\n", - " loop_JW_shadows(param, gggg, shadow_size=shadow_size).fun\n", - " - exact_energy\n", - " )\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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VsjPh+UBAQBA4+aywL148WJ9+umnKisrU//+/TV27FhFR0e7aroqunfvru7defrZHHUJba0uIb7ac6REP+w6opF9I8wuCQAAoFYueWly7ty5mjJlimw2m4KCgvTll1+qb9++euihh1wxnSRp9+7duvXWW3Xttdfq/vvv17///W9t2rRJdrvdZXPCHJVPuVdk5ppcCQAAwLm55An3iy++qMWLF+vKK690Hlu3bp1Gjx6tyMhI3XrrrQ0+55gxY2S323XFFVdo9+7dWrp0qX766Sd5eXmpT58+Sk1NbfA5YY7knmF6PWWvvj29PGDlC7kAAACNkUsC99GjR9W7d+8qx+Lj4zVv3jzdd999LgncW7duVVpamnr16uU8VlRUpPT0dG3YsKHB54N5LuoWIi8Pqw7mn9DOnOPqEe5ndkkAAABn5ZKWksTERL333nvVjvft21d79+51xZQaOHCg8vPzqxzz8/PT8OHDNW3aNJfMCXO08rIpoWuwpFOb4AAAADRmLuvhfvTRR/XnP/9Zhw4dkiQZhqFXXnnFZS9OPvTQQ5o9e7aKi4tdcn00LvRxAwCApqLBW0rsdrvsdrv+85//6I9//KPmzp2rgIAAlZeXy9vbWx9++GFDTylJuvLKK+Xp6amePXtq9OjRSkhIUFxcnHr16kWPbzOU3DNMf//PVq356ahKyk/K18stK1wCAADUW4OnFJvNpmHDhmnjxo1av369Nm3apC1btsjPz0+JiYku2/Vx48aN2rhxozZs2KANGzZo6dKlOnDggFq1aqV+/fpp9erVLpkX5ujetrU6BLbSwfwTStl1RJf3Dje7JAAAgBq55LFgbGyscnJyFB0drX79+qlfv36umKaKvn37qm/fvho3bpzzWH5+vjIyMrRx40aXzw/3slgsSu7ZVv9evU8rt+cSuAEAQKPlksD9l7/8RQ8++KCWLVum0NBQV0xRTXBwsGJiYhQbG6uYmBjFxcWpb9++SkpKUlJSkltqgHslRZ8K3CsyWR4QAAA0Xi55afKaa67R6tWr1bNnT91222165513tHXrVhmG4YrpJElvvvmmRo4cqezsbD311FO66KKL5Ofnp969e2vs2LEXdO158+apS5cu8vHxUUJCgtasWVOn8959911ZLBaNGjXqguZHzYZGhcrTZtG+oyXac6TE7HIAAABq5JLAvW3bNr399tu6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tVL37t31yCOP6Mz1ILjnTdu3336r3/zmN2rfvr0sFouWLVtW5fu63N+jR49q/Pjx8vf3V2BgoG655RYdP37cjT8FgRstwMqVKzVt2jT9+OOP+uqrr1RRUaErrrhCxcXFzjH33HOPPvnkEy1ZskQrV67UoUOHdO2115pYNRrK2rVr9dJLLykmJqbKce5583Ps2DENGzZMnp6e+vzzz7VlyxY9/fTTCgoKco554okn9M9//lMLFizQ6tWr1bp1a40cOVKlpaUmVo7zNXfuXM2fP18vvPCCtm7dqrlz5+qJJ57Q888/7xzDPW/aiouLFRsbq3nz5tX4fV3u7/jx47V582Z99dVX+vTTT/Xtt9/q1ltvddePcIoBtDA5OTmGJGPlypWGYRhGfn6+4enpaSxZssQ5ZuvWrYYkIyUlxawy0QCKioqMHj16GF999ZWRlJRk3HXXXYZhcM+bqwceeMC4+OKLz/q9w+EwIiIijCeffNJ5LD8/3/D29jbeeecdd5SIBnbVVVcZv//976scu/baa43x48cbhsE9b24kGR9++KHz13W5v1u2bDEkGWvXrnWO+fzzzw2LxWIcPHjQbbXzhBstTkFBgSQpODhYkpSamqqKigqNGDHCOaZXr17q1KmTUlJSTKkRDWPatGm66qqrqtxbiXveXH388ceKj4/XmDFjFBYWpgEDBmjRokXO73/66SdlZWVVue8BAQFKSEjgvjdRQ4cO1fLly7V9+3ZJUkZGhr777jtdeeWVkrjnzV1d7m9KSooCAwMVHx/vHDNixAhZrVatXr3abbV6uG0moBFwOBy6++67NWzYMPXr10+SlJWVJS8vLwUGBlYZGx4erqysLBOqREN49913lZaWprVr11b7jnvePO3evVvz58/X9OnT9ec//1lr167VnXfeKS8vL02cONF5b8PDw6ucx31vuh588EEVFhaqV69estlsstvtevTRRzV+/HhJ4p43c3W5v1lZWQoLC6vyvYeHh4KDg9367wCBGy3KtGnTtGnTJn333XdmlwIX2r9/v+666y599dVX8vHxMbscuInD4VB8fLwee+wxSdKAAQO0adMmLViwQBMnTjS5OrjCe++9p3//+996++231bdvX6Wnp+vuu+9W+/btuedoVGgpQYtxxx136NNPP9U333yjjh07Oo9HRESovLxc+fn5VcZnZ2crIiLCzVWiIaSmpionJ0cDBw6Uh4eHPDw8tHLlSv3zn/+Uh4eHwsPDuefNULt27dSnT58qx3r37q19+/ZJkvPe/nI1Gu5703XffffpwQcf1Lhx49S/f3/ddNNNuueeezRnzhxJ3PPmri73NyIiQjk5OVW+P3nypI4ePerWfwcI3Gj2DMPQHXfcoQ8//FBff/21unbtWuX7QYMGydPTU8uXL3cey8zM1L59+5SYmOjuctEALr/8cm3cuFHp6enOT3x8vMaPH+/8e+558zNs2LBqS35u375dnTt3liR17dpVERERVe57YWGhVq9ezX1vokpKSmS1Vo0yNptNDodDEve8uavL/U1MTFR+fr5SU1OdY77++ms5HA4lJCS4r1i3vZ4JmGTq1KlGQECAsWLFCuPw4cPOT0lJiXPMbbfdZnTq1Mn4+uuvjXXr1hmJiYlGYmKiiVWjoZ25SolhcM+bozVr1hgeHh7Go48+auzYscP497//bfj6+hpvvfWWc8zjjz9uBAYGGh999JGxYcMG4+qrrza6du1qnDhxwsTKcb4mTpxodOjQwfj000+Nn376yVi6dKkRGhpq3H///c4x3POmraioyFi/fr2xfv16Q5LxzDPPGOvXrzf27t1rGEbd7u+vf/1rY8CAAcbq1auN7777zujRo4fxu9/9zq0/B4EbzZ6kGj//+te/nGNOnDhh3H777UZQUJDh6+trXHPNNcbhw4fNKxoN7peBm3vePH3yySdGv379DG9vb6NXr17GwoULq3zvcDiMhx56yAgPDze8vb2Nyy+/3MjMzDSpWlyowsJC46677jI6depk+Pj4GN26dTP+8pe/GGVlZc4x3POm7Ztvvqnxv+ETJ040DKNu9/fIkSPG7373O6NNmzaGv7+/MWnSJKOoqMitP4fFMM7YjgkAAABAg6KHGwAAAHAhAjcAAADgQgRuAAAAwIUI3AAAAIALEbgBAAAAFyJwAwAAAC5E4AYAAABciMANAG72zTff6LrrrlOHDh3k5eWloKAg9ezZU2PGjNELL7yggoKCKuO7dOkii8ViUrWnvPbaa7JYLHr44YdNraMhrVixQhaLRTfffLPZpQBo5jzMLgAAWpK//e1vmjVrliSpd+/eSkhIkKenpzIzM7V06VK9//77io+P10UXXWRypQCAhkLgBgA3SU1N1cMPPyxPT0+99957GjVqVJXvs7Ky9NZbbykwMNCU+lqaIUOGaOvWrQoICDC7FADNHIEbANxk6dKlMgxD119/fbWwLUkRERG699573V9YC+Xr66tevXqZXQaAFoAebgBwk9zcXElS27Ztz/saL7/8smJiYtSqVStFREToD3/4g/Lz86uN27lzpx5++GElJiYqIiJCXl5e6tixoyZMmKDt27ef9frff/+9RowYIT8/PwUGBmrkyJFavXp1rTUdOXJE9913n3r06CEfHx8FBwfr17/+tb788stqY7t06SIfHx+VlpZWOX733XfLYrEoMjKy2jmjR4+WxWLRunXraq2j0g8//KBRo0apc+fO8vb2VkREhIYMGaIHH3xQx48fd46rqYe78lhtn1/2fBuGoXfeeUeXXXaZgoKC5OPjo969e+vhhx9WSUlJnWoG0LwRuAHATSrD5AcffKCcnJx6n3///fdr2rRpateuna688koZhqGFCxfqt7/9rQzDqDL25Zdf1t/+9jcVFxdr8ODB+u1vfyt/f3+9+eabGjx4sDZs2FDt+p9++qmSk5O1fPly9enTR1deeaX279+vSy65RCkpKTXWdPDgQQ0ZMkRPPfWUysvLNWrUKA0YMED/+9//NHLkSD377LNVxiclJamsrEw//vhjlePffPONJOnAgQPauXOn87hhGFq5cqUCAgI0YMCAc/4z+uSTTzR8+HB9/PHHateuna699loNGDBAR48e1dy5c5WXl1fr+REREZo4cWKNn+7du0uSbDabc7zD4dD48eN1ww03aO3atYqLi9P//d//qbi4WLNnz9all16qEydOnLNuAM2cAQBwi127dhmtWrUyJBl+fn7GxIkTjUWLFhlpaWnGyZMnz3pe586dDUlGRESEsW3bNufx3NxcIyoqypBkLF++vMo5KSkpxu7du6td69VXXzUkGZdeemmV44WFhUbbtm0NScarr77qPO5wOIwHHnjAkGRIMmbNmlXlvP/3//6fIcm44YYbjLKyMufxVatWGb6+vobNZjPWr19fbf4zr3PkyBHDYrEYffv2NSQZixYtcn63YcMGQ5Jx1VVXnfWfz5kuueQSQ5Lx/vvvV/tuzZo1RmFhofPX33zzjSHJmDhx4jmvm5KSYnh7exuBgYFGZmam8/gTTzxhSDKSk5ONw4cPO4+XlZUZt9xyiyHJeOCBB+pUO4Dmi8ANAG70v//9z4iMjHQG2MpPYGCgMXXqVOPQoUPVzqkM3GcG0UpPPfVUjUG4NsOGDTMsFouRn5/vPFYZhC+55JJq48vLy42OHTtWm2fXrl2GJKNNmzbGkSNHqp03ffp0Q5IxefJk57Hdu3cbkoykpCTnsaVLlxqSjNdff93w9vY2xo8f7/zun//8pyHJeOKJJ+r0s/Xu3duQVOVnO5u6Bu79+/cbERERhs1mM/773/86j1dUVBihoaFG69atjaysrGrnlZSUGBEREUZQUJBht9vrVD+A5omWEgBwo8svv1w7d+7U0qVLddttt2ngwIHy8PBQfn6+5s+fr7i4OGVmZtZ47hVXXFHtWHR0tCTp8OHD1b47fvy43nnnHT3wwAOaMmWKbr75Zt188806fPiwDMPQrl27nGNXrVolSRo3bly163h6emr06NHVjn/33XeSpF//+tcKDg6u9v1NN91U5dqS1LVrV3Xq1Ek//vijs497xYoVzutcdNFFWrlypXN85XfJycnVrl+TQYMGOedeu3atHA5Hnc47mxMnTujqq69WVlaWnn766Sr3IC0tTXl5eRo6dKjCw8OrnduqVSsNGjRIx44d044dOy6oDgBNG6uUAICbeXl56ZprrtE111wjScrPz9e7776rP//5z8rJydEdd9yhr776qtp5HTt2rHbMz89PklRWVlbl+Ndff61x48Y5X9SsSVFRkfPvDx06JEnq3LlzjWO7dOlS7VjlOTV9d+bxgwcPVjmelJSkN998Uz/++KOSk5O1YsUK9enTR2FhYUpOTtbKlSu1c+dOde/eXd9++638/Pw0cODAs/4cZ3rssce0ceNGffLJJ/rkk08UFBSkiy++WL/97W914403ysfHp07XqXTzzTcrLS1Nt9xyi+66664q3+3Zs0eS9NVXX51zY6K8vDz17NmzXnMDaD4I3ABgssDAQN12221q3769rr76an3zzTcqKSmRr69vlXFWa93+UPL48eO6/vrrdfToUc2cOVPjxo1T586d1apVK1ksFt1www165513qr1o2dDOFkKTk5P15ptvasWKFYqJidHGjRs1depU53ezZ8/WihUrdOLECeXl5enKK6+s8qJibSIjI7Vu3Tp9/fXX+vTTT7Vy5Upn+H7iiSeUkpKikJCQOl3rkUce0XvvvaeLL75YL774YrXvK5+eR0VFadiwYbVeq65zAmieCNwA0EhcdtllkiS73a78/PxqgbuuVq1apSNHjmj06NGaPXt2te93795d7Vi7du0kSXv37q3xmjUdb9++fa3nVD4B7tChQ5XjSUlJkk61i8TGxsowDGfLyEUXXSRvb29n4Jbq3k5SycPDQ1dccYWz/WPv3r36/e9/r6+//lpz587VE088cc5rfPjhh5o1a5Y6d+6spUuXysvLq9qYyj9x6NWrl1577bV61QigZaGHGwDc5FxPlCuXw/Py8lJoaOh5z3Ps2DFJNbeg7Ny5U2lpadWODx8+XJL03nvvVfvu5MmT+uCDD6odv/jiiyVJX3zxRY1rgb/11ltVrl2pe/fuioyM1I8//qgvvvhCFovFGap9fHycfdz17d8+m86dO+uBBx6QJG3atOmc4zMyMnTTTTfJ19dXH3300VnXTR88eLACAgK0cuVKHT169IJqBNC8EbgBwE0eeugh3XfffVVeVqx08OBB/eEPf5Ak/fa3v63xiWpdVb5IuXTp0io93Pn5+brllltUUVFR7ZwxY8YoJCREK1as0Ouvv+48bhiGZs2apX379lU7p1u3brrqqqtUVFSku+66q8p1U1JSNH/+fNlsNk2bNq3auZXrcb/xxhvq06dPlVCbnJysAwcO6LPPPqtX/7YkPfvss8rKyqp2/LPPPpOkGjfWOVNubq6uvvpqlZSU6I033lBsbOxZx3p7e+v+++9XUVGRrr322hr/5ODgwYN6880361w/gOaJlhIAcJPjx4/rH//4h5566ilFR0erT58+8vHx0YEDB7R69WpVVFQoKipKzz333AXNEx8fr1/96lf66quvFB0d7XxCvGLFCoWGhurqq6/WRx99VOUcPz8/vfLKK7ruuut08803a/78+erWrZsyMjK0Y8cOTZkyRYsWLao210svvaThw4frjTfe0MqVK5WYmKjc3FytWLFCdrtdTz/9tOLi4qqdl5SUpLfeekulpaXVnmBX9nFXfufhUff/VM2ePVv33nuvYmNj1aNHDxmGoYyMDG3fvl3BwcG69957az1/wYIF2rt3ryIiIvTxxx/r448/rjbm4osv1uTJkyVJDz74oLZt26Y333xTvXv31oABA9S1a1eVl5crMzNTW7ZsUUxMjHPFFgAtE4EbANzkr3/9q+Lj4/Xf//5XGRkZWrVqlQoKCuTv768hQ4bo6quv1u23367WrVtf8FwfffSRHn30Ub333nv6/PPPFRYWpnHjxunvf/+7/vSnP9V4TuULm7NmzdKaNWu0detWDR48WC+//LIyMzNrDNwdOnTQ2rVrNWfOHC1btkxLly6Vr6+vLr/8cv3pT3+qcSlDqWqbyC8Dd2Ufd1lZWb3bSZ5//nl98cUXSk1N1eeffy7p1FPt6dOna/r06dX6yX/JbrdLkrKysqo86f+lysBttVr1xhtvaPTo0Vq4cKHWrl2rtLQ0BQUFKTIyUvfdd5/Gjh1br58BQPNjMVz9mjoAAADQgtHDDQAAALgQgRsAAABwIQI3AAAA4EIEbgAAAMCFCNwAAACACxG4AQAAABcicAMAAAAuROAGAAAAXIjADQAAALgQgRsAAABwIQI3AAAA4EIEbgAAAMCFCNwAAACAC/1/Tt7HAfqwNEkAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.figure(figsize=(8, 5))\n", - "plt.xlabel(\"Shadow size\", fontsize=15)\n", - "plt.ylabel(r\"$|\\frac{E - E_{ground}}{E_{ground}}|$\", fontsize=20)\n", - "plt.plot(shadow_sizes, [-e / exact_energy for e in energies])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As could be expected, the estimation can be worse than what we got before : we added both randomness and sampling issues to the problem. Raising shadow size will allow more and more precise results. However, it can also be closer to the exact value for the same reasons." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Derandomized measurements" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we try out the derandomized measurements method. To implement this one, we need to decompose the Hamiltonian into individual Pauli strings, rather than group them when they share the same leading coefficient as we did before, as it reduced the number of estimations." - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [], - "source": [ - "coeff_non_fact = [\n", - " -0.81261,\n", - " 0.171201,\n", - " 0.171201,\n", - " -0.2227965,\n", - " -0.2227965,\n", - " 0.16862325,\n", - " 0.174349,\n", - " 0.12054625,\n", - " 0.12054625,\n", - " 0.165868,\n", - " 0.165868,\n", - " -0.04532175,\n", - " -0.04532175,\n", - " 0.04532175,\n", - " 0.04532175,\n", - "]\n", - "\n", - "paulis_str = [\n", - " \"1111\",\n", - " \"Z111\",\n", - " \"1Z11\",\n", - " \"11Z1\",\n", - " \"111Z\",\n", - " \"ZZ11\",\n", - " \"11ZZ\",\n", - " \"Z1Z1\",\n", - " \"1Z1Z\",\n", - " \"1ZZ1\",\n", - " \"Z11Z\",\n", - " \"YYXX\",\n", - " \"XXYY\",\n", - " \"XYYX\",\n", - " \"YXXY\",\n", - "]" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "def exp_value_JW_non_fact(outcomes):\n", - " return sum(\n", - " [\n", - " c * exp_value(sigma, outcomes)\n", - " for c, sigma in zip(coeff_non_fact, paulis_str)\n", - " ]\n", - " )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Then, we ask the derandomization algorithm to return $60$ suitable Pauli measurements regarding our input Pauli observables. $60$ is arbitrary, but is small enough that the algorithm runs quickly and large enough that it gives good results." - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ZZZZ measurements : 18, XXYY measurements : 11, YXXY measurements : 11, XYYX measurements : 10, YYXX measurements : 10 : total = 60 measurements\n" - ] - } - ], - "source": [ - "measurements = derandomization(60, paulis_str)\n", - "print(\n", - " f\"ZZZZ measurements : {measurements.count('ZZZZ')}, XXYY measurements : {measurements.count('XXYY')}, \"\n", - " + f\"YXXY measurements : {measurements.count('YXXY')}, XYYX measurements : {measurements.count('XYYX')}, \"\n", - " + f\"YYXX measurements : {measurements.count('YYXX')} : total = 60 measurements\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see, since all Pauli observables appearing in the Jordan-Wigner Hamiltonian involving the $Z$-basis never involve another basis, we find that it is always worth it to measure Pauli string $ZZZZ$ rather than $ZZZX$, or $ZYZZ$, etc. This is a sign that our cost function is doing its job !" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "def quantum_loop_derand(param, in_state, r=reg):\n", - " \"\"\"\n", - " Args:\n", - " param (np.array): time parameters for each mixing Hamiltonian. There are 2p time parameters in param.\n", - " in_state (qubit.Qobj): initial state.\n", - " \"\"\"\n", - " seq = Sequence(r, DigitalAnalogDevice)\n", - " seq.declare_channel(\"ch0\", \"rydberg_global\")\n", - " middle = len(param) // 2\n", - "\n", - " for tau, t in zip(param[middle:], param[:middle]):\n", - " pulse_1 = Pulse.ConstantPulse(tau, 1.0, 0, 0)\n", - " pulse_2 = Pulse.ConstantPulse(t, 1.0, 1.0, 0)\n", - " seq.add(pulse_1, \"ch0\")\n", - " seq.add(pulse_2, \"ch0\")\n", - "\n", - " seq.measure(\"ground-rydberg\")\n", - " simul = QutipEmulator.from_sequence(seq, sampling_rate=0.05)\n", - " simul.set_initial_state(in_state)\n", - "\n", - " # Classical shadow estimation\n", - " rho = simul.run().get_final_state().proj()\n", - " outcomes = classical_shadow_derand(rho, measurements)\n", - " return exp_value_JW_non_fact(outcomes)\n", - "\n", - "\n", - "def loop_JW_derand(param, in_state):\n", - " res = minimize(\n", - " quantum_loop_derand,\n", - " param,\n", - " method=\"Nelder-Mead\",\n", - " args=in_state,\n", - " options={\"return_all\": True, \"maxiter\": 150, \"adaptive\": True},\n", - " )\n", - " return res" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "measurement_sizes = [20, 30, 40, 60, 80, 100]\n", - "energies_derand = []\n", - "for meas_size in measurement_sizes:\n", - " measurements = derandomization(meas_size, paulis_str)\n", - " energies_derand.append(\n", - " abs(loop_JW_derand(param, gggg).fun - exact_energy) / abs(exact_energy)\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "plt.figure(figsize=(8, 5))\n", - "plt.xlabel(\"Measurement size\", fontsize=15)\n", - "plt.ylabel(r\"$|\\frac{E - E_{ground}}{E_{ground}}|$\", fontsize=20)\n", - "plt.plot(measurement_sizes, energies_derand)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We consistently obtain accurate results using this derandomized technique, and we obtain them far quicker than when dealing with randomized classical shadows. For roughly the same number of samples ($\\sim 60$ for each method, be it for shadow size or number of measurements), we experience much less computing time using the derandomized method. This was to be expected : by restricting the observables to Pauli strings, we allow for efficient estimation that can be easily computed in $O(M\\times n)$, as well as remove randomness problematic with higher-weight observables (such as $YYXX$ or $YXXY$).\n", - "\n", - "Note that we obtain $2\\%$ accuracy after about $50$ $Z-$ basis measurements (fluorescence) of the output state, rotated before each sampling in the bases returned by the derandomization algorithm." - ] + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Efficient estimation techniques for Variational Quantum Simulation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Introduction" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$\\newcommand{\\ket}[1]{\\left|#1\\right>} \\newcommand{\\bra}[1]{\\left<#1\\right|}$\n", + "This notebook's purpose is to introduce the concept of classical shadow estimation, as well as its use in **VQS** (**V**ariational **Q**uantum **S**imulation). This technique, introduced in [this article by Huang, Kueng and Preskill](https://arxiv.org/abs/2002.08953), is used for efficiently estimating multiple observables, and is extremely powerful in that regard, asymptotically reaching theoretical lower bounds of quantum information theory regarding the number of required samples of a given state for estimation ([see here for details](https://arxiv.org/abs/2101.02464)). \n", + "\n", + "The primary goal of this notebook is to estimate the groundstate energy of the $H_2$ molecule, using a VQS. We will first implement the method of random classical shadows in Python. Then, we'll introduce its derandomized counterpart, which is particularly useful in our setting. We'll finally describe the VQS, and benchmark the estimation methods we introduced for computing the molecule's energy. This notebook draws some inspiration from [this PennyLane Jupyter notebook](https://pennylane.ai/qml/demos/tutorial_classical_shadows.html) on quantum machine learning and classical shadows." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Random classical shadows" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Main ideas and implementation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Classical shadow estimation relies on the fact that for a particular\n", + "choice of measurement, we can efficiently store snapshots of the state\n", + "that contain enough information to accurately predict linear functions\n", + "of observables.\n", + "\n", + "Let us consider an $n$-qubit quantum state $\\rho$ (prepared by a\n", + "pulse sequence) and apply a random unitary $U$ to the state:\n", + "\n", + "$$\\rho \\to U \\rho U^\\dagger.$$\n", + "\n", + "Next, we measure in the computational basis and obtain a bit string of\n", + "outcomes $|b\\rangle = |0011\\ldots10\\rangle$. If the unitaries $U$ are\n", + "chosen at random from a particular ensemble, then we can store the\n", + "reverse operation $U^\\dagger |b\\rangle\\langle b| U$ efficiently in\n", + "classical memory. We call this a *snapshot* of the state. Moreover, we\n", + "can view the average over these snapshots as a measurement channel:\n", + "\n", + "$$\\mathbb{E}\\left[U^\\dagger |b\\rangle\\langle b| U\\right] = \\mathcal{M}(\\rho).$$\n", + "\n", + "We restrict ourselves to unitary ensembles that define a tomographically complete set of\n", + "measurements (i.e $\\mathcal{M}$ is invertible), therefore :\n", + "\n", + "$$\\rho = \\mathbb{E}\\left[\\mathcal{M}^{-1}\\left(U^\\dagger |b\\rangle\\langle b| U \\right)\\right].$$\n", + "\n", + "If we apply the procedure outlined above $N$ times, then the collection\n", + "of inverted snapshots is what we call the *classical shadow*\n", + "\n", + "$$S(\\rho,N) = \\left\\{\\hat{\\rho}_1= \\mathcal{M}^{-1}\\left(U_1^\\dagger |b_1\\rangle\\langle b_1| U_1 \\right)\n", + ",\\ldots, \\hat{\\rho}_N= \\mathcal{M}^{-1}\\left(U_N^\\dagger |b_N\\rangle\\langle b_N| U_N \\right)\n", + "\\right\\}.$$\n", + "\n", + "Since the shadow approximates $\\rho$, we can now estimate **any**\n", + "observable with the empirical mean:\n", + "\n", + "$$\\langle O \\rangle = \\frac{1}{N}\\sum_i \\text{Tr}{\\hat{\\rho}_i O}.$$\n", + "\n", + "We will be using a median-of-means procedure in practice." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We start by defining several useful quantities, such as the unitary matrices associated with Pauli measurements : the Hadamard matrix, change of basis from $\\{\\ket{0}, \\ket{1}\\}$ to the eigenbasis of $\\sigma_X$, $\\{\\ket{+}, \\ket{-}\\}$, and its $\\sigma_Y, \\sigma_Z$ counterparts. We will then draw randomly from this tomographically complete set of $3$ unitaries.\n", + "\n", + "Note that we will need $4$ qubits for our VQS problem : we will explain the mapping from the molecule to qubits later." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import qutip\n", + "import matplotlib.pyplot as plt\n", + "from scipy.optimize import minimize\n", + "\n", + "from pulser import Register, Sequence, Pulse\n", + "from pulser.devices import DigitalAnalogDevice\n", + "from pulser_simulation import QutipEmulator" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "num_qubits = 4\n", + "zero_state = qutip.basis(2, 0).proj()\n", + "one_state = qutip.basis(2, 1).proj()\n", + "hadamard = 1 / np.sqrt(2) * qutip.Qobj([[1.0, 1.0], [1.0, -1.0]])\n", + "h_mul_phase = qutip.Qobj(np.array([[1.0, 1], [1.0j, -1.0j]])) / np.sqrt(2)\n", + "unitary_ensemble = [hadamard, h_mul_phase, qutip.qeye(2)]\n", + "\n", + "g = qutip.basis(2, 1)\n", + "r = qutip.basis(2, 0)\n", + "n = r * r.dag()\n", + "\n", + "sx = qutip.sigmax()\n", + "sy = qutip.sigmay()\n", + "sz = qutip.sigmaz()\n", + "\n", + "gggg = qutip.tensor([g, g, g, g])\n", + "ggrr = qutip.tensor([g, g, r, r])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first define a function that spits out a random bitstring sampled from a given density matrix." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "def measure_bitstring(state):\n", + " \"\"\"Auxiliary function that returns a bitstring according to the measure of a quantum state.\"\"\"\n", + " probs = np.real(state.diag())\n", + " probs /= np.sum(probs)\n", + " x = np.nonzero(np.random.multinomial(1, probs))[0][0]\n", + " bitstring = np.binary_repr(x, num_qubits)\n", + " return bitstring" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will need to compute the number of shadows needed given :\n", + "\n", + "* A list of observables $o_i$\n", + "* Desired precision on expectation values $\\epsilon$ : if $\\tilde{o}_i$ is the estimated expectation value for observable $o_i$, we wish for $|Tr(o_i \\rho) - \\tilde{o}_i| \\leq \\epsilon$\n", + "* Failure probability $\\delta$ : we wish for the above equation to be satisfied with probability $1-\\delta$\n", + "\n", + "Precise formulae are given in [Huang et al.](https://arxiv.org/abs/2002.08953)\n", + "The integer $K$ returned by the function will serve as the number of blocks in our median of means procedure afterwards." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def compute_shadow_size(delta, epsilon, observables):\n", + " \"\"\"Helper function.\n", + "\n", + " Computes both the number of shadows needed as well as the size of blocks needed\n", + " for the median_of_means method in order to approximate the expectation value of M\n", + " (linear) observables with additive error epsilon and fail probability delta.\n", + "\n", + " Args:\n", + " delta (float): Failure probability.\n", + " epsilon (float): Additive error on expectation values.\n", + " observables (list[qutip.Qobj]): Observables the expectation value of which is to be computed.\n", + " \"\"\"\n", + " M = len(observables)\n", + " K = 2 * np.log(2 * M / delta)\n", + " shadow_norm = (\n", + " lambda op: np.linalg.norm(\n", + " op - np.trace(op) / 2 ** int(np.log2(op.shape[0])), ord=np.inf\n", + " )\n", + " ** 2\n", + " )\n", + " # Theoretical number of shadows per cluster in the median of means procedure :\n", + " # N = 34 * max(shadow_norm(o) for o in observables) / epsilon ** 2\n", + " # We use N = 20 here to allow for quick simulation\n", + " N = 20\n", + " return int(np.ceil(N * K)), int(K)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we design a function that returns snapshots (bitstrings) of the rotated state as well as the sampled unitaries used to rotate the state $\\rho$." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_classical_shadow(rho, shadow_size):\n", + " \"\"\"\n", + " Given a state rho, creates a collection of snapshots consisting of a bit string\n", + " and the index of a unitary operation.\n", + "\n", + " Returns:\n", + " Tuple of two numpy arrays. The first array contains measurement outcomes as bitstrings\n", + " while the second array contains the index for the sampled Pauli's (0,1,2=X,Y,Z).\n", + " \"\"\"\n", + " # sample random Pauli measurements uniformly\n", + " unitary_ids = np.random.randint(0, 3, size=(shadow_size, num_qubits))\n", + " outcomes = []\n", + " for ns in range(shadow_size):\n", + " unitmat = qutip.tensor(\n", + " [unitary_ensemble[unitary_ids[ns, i]] for i in range(num_qubits)]\n", + " )\n", + " outcomes.append(measure_bitstring(unitmat.dag() * rho * unitmat))\n", + "\n", + " # combine the computational basis outcomes and the sampled unitaries\n", + " return (outcomes, unitary_ids)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We then reconstruct an estimate of the quantum state from the sampled bitstrings, using the inverse quantum channel $\\mathcal{M}^{-1}$ defined above. In the particular case of Pauli measurements, we can actually compute the inverse channel : \n", + "\n", + "$$\\mathcal{M}^{-1} = \\otimes_{i=1}^n (3 U_i \\ket{b_i}\\bra{b_i} U^\\dagger_i - \\mathbb{1}_2)$$\n", + "\n", + "where $i$ runs over all qubits : $\\ket{b_i}$, $b_i \\in \\{0,1\\}$, is the single-bit snapshot of qubit $i$ and $U_i$ is the sampled unitary corresponding to the snapshot, acting on qubit $i$." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "def snapshot_state(outcome_ns, unitary_ids_ns):\n", + " \"\"\"\n", + " Reconstructs an estimate of a state from a single snapshot in a shadow.\n", + "\n", + " Implements Eq. (S44) from https://arxiv.org/pdf/2002.08953.pdf\n", + "\n", + " Args:\n", + " outcome_ns: Bitstring at ns\n", + " unitary_ids_ns: Rotation applied at ns.\n", + "\n", + " Returns:\n", + " Reconstructed snapshot.\n", + " \"\"\"\n", + " state_list = []\n", + "\n", + " for k in range(num_qubits):\n", + " op = unitary_ensemble[unitary_ids_ns[k]]\n", + " b = zero_state if outcome_ns[k] == \"0\" else one_state\n", + " state_list.append(3 * op * b * op.dag() - qutip.qeye(2))\n", + "\n", + " return qutip.tensor(state_list)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We finally write a median of means procedure. We feed it an observable, the list of snapshots computed above and the number of blocks needed. It returns the median of the means of the observable acting on the snapshots in each block." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def _median_of_means(obs, snap_list, K):\n", + " if K > len(snap_list): # preventing the n_blocks > n_observations\n", + " K = int(np.ceil(len(snap_list) / 2))\n", + " # dividing seq in K random blocks\n", + " indic = np.array((list(range(K)) * int(len(snap_list) / K)))\n", + " np.random.shuffle(indic)\n", + " # computing and saving mean per block\n", + " means = []\n", + " for block in range(K):\n", + " states = [snap_list[i] for i in np.where(indic == block)[0]]\n", + " exp = qutip.expect(obs, states)\n", + " means.append(np.mean(exp))\n", + " return np.median(means)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reconstructing a given quantum state" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us try out the efficiency of this method. We will reconstruct a given density matrix from classical shadows estimation, and observe the evolution of the trace distance between the original state and its reconstruction according to the number of shadows used." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "def state_reconstruction(snaps):\n", + " return sum(snaps) / len(snaps)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Original density matrix :\n", + "[[0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]\n", + " [0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]\n", + " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", + " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]]\n", + "Shadow reconstruction :\n", + "[[ 0.47+0.j 0.51+0.j 0. +0.j 0.01+0.01j]\n", + " [ 0.51-0.j 0.53+0.j 0. +0.01j 0.01+0.j ]\n", + " [ 0. -0.j 0. -0.01j 0. +0.j -0.01-0.01j]\n", + " [ 0.01-0.01j 0.01-0.j -0.01+0.01j -0.01+0.j ]]\n" + ] } - ], - "metadata": { - "celltoolbar": "Tags", - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" + ], + "source": [ + "num_qubits = 2\n", + "shadow_size = 10000\n", + "rho_1 = (\n", + " (\n", + " qutip.tensor([qutip.basis(2, 0), qutip.basis(2, 0)])\n", + " + qutip.tensor([qutip.basis(2, 0), qutip.basis(2, 1)])\n", + " )\n", + " .proj()\n", + " .unit()\n", + ")\n", + "print(\"Original density matrix :\")\n", + "print(rho_1.full())\n", + "outcomes, unitary_ids = calculate_classical_shadow(rho_1, shadow_size)\n", + "snapshots = [\n", + " snapshot_state(outcomes[ns], unitary_ids[ns]) for ns in range(shadow_size)\n", + "]\n", + "print(\"Shadow reconstruction :\")\n", + "print(np.around(state_reconstruction(snapshots).full(), 2))\n", + "\n", + "dist = np.zeros(5)\n", + "shadow_sizes = [100, 1000, 2000, 5000, 10000]\n", + "for i, shadow_size in enumerate(shadow_sizes):\n", + " outcomes, unitary_ids = calculate_classical_shadow(rho_1, shadow_size)\n", + " snapshots = [\n", + " snapshot_state(outcomes[ns], unitary_ids[ns])\n", + " for ns in range(shadow_size)\n", + " ]\n", + " dist[i] = qutip.tracedist(state_reconstruction(snapshots), rho_1)\n", + "num_qubits = 4" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" } + ], + "source": [ + "plt.plot(shadow_sizes, dist)\n", + "plt.xlabel(\"Shadow size\")\n", + "plt.ylabel(r\"$||\\rho - \\hat{\\rho}||_1$\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can expect, the estimation gets better and better as shadow size gets larger, with about $2$% accuracy at $10000$ shadows. This mostly serves as a reality check, as we will be using classical shadows to estimate observables acting on quantum states, not to reconstruct those states." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Derandomized Paulis" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Derandomization Algorithm" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Randomized classical shadows are useful when dealing with low-weight, general observables. However, suppose, as is the case when estimating the Hamiltonian of the $H_2$ molecule written as a sum of Pauli strings, that we're dealing with Pauli observables of varying weights. In this setting, choosing wisely each Pauli measurement instead of randomly drawing a basis is particularly useful : indeed, say one wants to measure observable $\\sigma_x^1 \\otimes \\sigma_x^2 \\otimes \\dots \\otimes \\sigma_x^n$. Using random rotations in each Pauli $X,Y$ or $Z$ basis and projection in the $Z$ (computational) basis, there is a probability $\\frac{1}{3^n}$ to get each measurement basis right (i.e. rotate the system using the Hadamard matrix). This is extremely unlikely and unefficient as the number of qubits goes up. [Huang et al](https://arxiv.org/abs/2103.07510) outline an interesting greedy algorithm used for choosing suitable measurement bases for the efficient estimation of $L$ $n-$qubit Pauli strings, $\\{O_i\\}$. \n", + "\n", + "Feeding these observables and chosen Pauli measurements {P_i} as input, the algorithm aims at optimizing a certain cost function. This function, labeled $Conf_\\epsilon(O_i, P_j)$ is such that, if $Conf_\\epsilon(O_i, P_j) \\leq \\frac{\\delta}{2}$, then the empirical averages $\\tilde{\\omega_l}$ of each Pauli observable $O_l$ will be $\\epsilon$-close to its true average $Tr(\\rho O_l)$ with probability $1-\\delta$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to implement this cost function, we first need to design two auxiliary functions. The first one decides if a given Pauli measurement $p$ is compatible with (\"hits\") a Pauli observable $o$. This means that each time $o$ acts non-trivially on a qubit $q_i$ with Pauli matrix $\\sigma \\in \\{\\sigma_X, \\sigma_Y, \\sigma_Z\\}, \\sigma \\neq \\mathbb{1}$, $p$ acts on $q_i$ with $\\sigma$. We denote it by $o \\triangleright p$." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def hits(p, o, end=-1):\n", + " \"\"\"Determines if measurement p hits observable o\n", + "\n", + " Args:\n", + " p (str): Pauli string in str format (ex \"XYZ\"), measurement\n", + " o (str): same as above, observable (ex \"11ZY\")\n", + " end (int): index before which to check if p hits o\n", + " \"\"\"\n", + " if end != -1:\n", + " o = o[:end]\n", + " for i, x in enumerate(o):\n", + " if not (x == p[i] or x == \"1\"):\n", + " return False\n", + " return True" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The second function simply computes the number of qubits observable $o$ acts non-trivially upon." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def weight(o, start=0):\n", + " o_k = o[start:]\n", + " return len(o_k) - o_k.count(\"1\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now implement the conditioned cost function using these auxiliary functions. We call it \"conditioned\", since we feed it only the first $m \\times n + k$ single-qubit Pauli measurements, and average over the others, not yet determined ones." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def cond_conf(o, P_sharp):\n", + " \"\"\"Returns the (modified) conditionned expectation value of the cost function depending\n", + " on already chosen Paulis in P_sharp.\n", + "\n", + " Args:\n", + " o (list[str]): list of Pauli strings to be measured\n", + " P_sharp (list[str]): list of already chosen Paulis\n", + " \"\"\"\n", + " # Hyperparameters : see Huang et al. for more details\n", + " eta = 0.9\n", + " nu = 1 - np.exp(-eta / 2)\n", + " L = len(o)\n", + " m = len(P_sharp) - 1 # index of last chosen Pauli string\n", + " k = (\n", + " len(P_sharp[-1]) - 1\n", + " ) # index of last chosen Pauli matrix in mth Pauli string\n", + " result = 0\n", + " for l in range(0, L):\n", + " v = 0\n", + " for m_prime in range(0, m):\n", + " v += (eta / 2) * int(hits(P_sharp[m_prime], o[l]))\n", + " v -= np.log(\n", + " 1\n", + " - (nu / 3 ** (weight(o[l], start=k + 1)))\n", + " * hits(P_sharp[m], o[l], end=k + 1)\n", + " )\n", + " result += np.exp(-v)\n", + " return result" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we design a simple greedy algorithm which purpose is to minimize this conditioned cost function, choosing one single-qubit Pauli at a time." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "def derandomization(M, o):\n", + " \"\"\"Derandomization algorithm returning best Pauli indices according to a greedy algorithm\n", + " that aims at minimizing the cost function above.\n", + "\n", + " Args:\n", + " M (int): number of measurements\n", + " n (int): number of qubits (size of Pauli strings)\n", + " epsilon (float): desired accuracy on observable expectation values\n", + " o (list[str]): list of Pauli strings to be measured\n", + " \"\"\"\n", + " n = len(o[0])\n", + " P_sharp = []\n", + " for m in range(M):\n", + " P_sharp.append(\"\")\n", + " for k in range(n):\n", + " P_sharp_m = P_sharp[m]\n", + " P_sharp[m] += \"X\"\n", + " valmin = cond_conf(o, P_sharp)\n", + " argmin = \"X\"\n", + " for W in [\"Y\", \"Z\"]:\n", + " P_sharp[m] = P_sharp_m + W\n", + " val_W = cond_conf(o, P_sharp)\n", + " if val_W < valmin:\n", + " valmin = val_W\n", + " argmin = W\n", + " P_sharp[m] = P_sharp_m + argmin\n", + " return P_sharp" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Estimating expectation values from Pauli measurements" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that we have our Pauli measurements, we proceed differently from randomized classical shadows, where we gave an estimate of the actual quantum channels. Here, we're only interested in the Pauli averages $\\tilde{\\omega}_l$, that we can infer from Pauli measurements $p$ that **hit** observable $o_l$. Indeed, we have the following formula :\n", + "\n", + "$$\\tilde{\\omega}_{l}=\\frac{1}{h\\left(\\mathbf{o}_{l} ;\\left[\\mathbf{p}_{1}, \\ldots, \\mathbf{p}_{M}\\right]\\right)} \\sum_{m: \\mathbf{o}_{l} \\triangleright \\mathbf{p}_{m}} \\prod_{j: \\mathbf{o}_{l}[j] \\neq I} \\mathbf{q}_{m}[j]$$\n", + "\n", + "where $h\\left(\\mathbf{o}_{l} ;\\left[\\mathbf{p}_{1}, \\ldots, \\mathbf{p}_{M}\\right]\\right)$ is the number of times a Pauli measurement $p_i$ is such that $o \\triangleright p_i$, and $\\mathbf{q}_m$ is the output of the measurement of Pauli string $p_m$ ($\\mathbf{q}_m \\in \\{\\pm 1\\}^n$)." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "def _pauli_index(letter):\n", + " if letter == \"X\":\n", + " return 0\n", + " elif letter == \"Y\":\n", + " return 1\n", + " else:\n", + " return 2" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def pauli_string_value(x, sigma):\n", + " \"\"\"Returns the evaluation of a Pauli string sigma in a bitstring state $|x>$,\n", + " assuming the state is already rotated in the needed eigenbases of all single-qubit Paulis.\n", + "\n", + " NB : Faster than using qutip.measure due to not returning the eigenstates...\n", + "\n", + " Args:\n", + " x (str): input bitstring\n", + " sigma (str): input Pauli string to be measured on |x>\n", + " \"\"\"\n", + " outcomes = []\n", + " for i, q in enumerate(x):\n", + " if q == \"0\":\n", + " outcomes.append((sigma[i], 1))\n", + " else:\n", + " outcomes.append((sigma[i], -1))\n", + " return outcomes" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def classical_shadow_derand(rho, measurements):\n", + " \"\"\"Returns the n-strings of ±1 corresponding to measurements in the input list on state rho.\n", + "\n", + " Args:\n", + " rho (qutip.Qobj): input state as a density matrix\n", + " measurements (list[str]): derandomized measurement bases in which to measure state rho\n", + "\n", + " Returns:\n", + " Tuple of two numpy arrays. The first array contains measurement outcomes as bitstrings\n", + " while the second array contains the index for the derandomized Pauli's (0,1,2=X,Y,Z).\n", + " \"\"\"\n", + " # Fill the unitary ids with derandomized measurements ids\n", + " shadow_size = len(measurements)\n", + " outcomes = []\n", + " for ns in range(shadow_size):\n", + " # multi-qubit change of basis\n", + " unitmat = qutip.tensor(\n", + " [\n", + " unitary_ensemble[_pauli_index(measurements[ns][i])]\n", + " for i in range(num_qubits)\n", + " ]\n", + " )\n", + " x = measure_bitstring(unitmat.dag() * rho * unitmat)\n", + " outcomes.append(pauli_string_value(x, measurements[ns]))\n", + " # ±1 strings\n", + " return outcomes" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "def exp_value(input_pauli, pm_strings):\n", + " \"\"\"Computes an estimation of the expectation value of a given Pauli string given multiple ±1 bitstring\n", + " outcomes.\n", + " \"\"\"\n", + " sum_product, cnt_match = 0, 0\n", + "\n", + " for single_measurement in pm_strings:\n", + " not_match = False\n", + " product = 1\n", + "\n", + " for i, pauli in enumerate(input_pauli):\n", + " if pauli != single_measurement[i][0] and pauli != \"1\":\n", + " not_match = True\n", + " break\n", + " if pauli != \"1\":\n", + " product *= single_measurement[i][1]\n", + " if not_match:\n", + " continue\n", + "\n", + " sum_product += product\n", + " cnt_match += 1\n", + " if cnt_match == 0:\n", + " return f\"No measurement given for {input_pauli}\"\n", + " return sum_product / cnt_match" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Variational Quantum Simulation for the $H_2$ molecule" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main problem with usual variational classical algorithms, the classical counterparts of VQS, is computing the value of the $2^n \\times 2^n$ matrix on the output state vector $\\bra{\\psi}H\\ket{\\psi}$ after each loop of the algorithm, which grows exponentially in the size of the system. The purpose of VQS algorithms is to offer a solution which time complexity only grows polynomially, thanks to reading all the important properties on the quantum state. Therefore, we need accurate and efficient methods to estimate these properties, which we'll present afterwards.\n", + "\n", + "For now, let's focus on what makes a VQS algorithm, specifically for computing the groundstate energy of the $H_2$ molecule." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Jordan-Wigner Hamiltonian (cost function)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We need to write the Hamiltonian in a way that's compatible with the formalism of quantum computing. We first second-quantize the Hamiltonian, obtaining an expression in terms of fermionic operators $a, a^\\dagger$. Then, we use the Jordan-Wigner transformation, which maps the fermionic operators to Pauli matrices. We obtain the Hamiltonian below, acting on $4$ qubits, decomposed in terms of the coefficients in front of the Pauli matrices.\n", + "\n", + "[This article by Seeley et al.](https://math.berkeley.edu/~linlin/2018Spring_290/SRL12.pdf) gives us the value of \n", + "$H_{JW}$." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$H_{J W}=-0.81261 \\mathbb{1}+0.171201 \\sigma_{0}^{z}+0.171201 \\sigma_{1}^{z}-0.2227965 \\sigma_{2}^{z} \\\\\n", + "-0.2227965 \\sigma_{3}^{z} +0.16862325 \\sigma_{1}^{z} \\sigma_{0}^{z}+0.12054625 \\sigma_{2}^{z} \\sigma_{0}^{z} \\\\\n", + "+0.165868 \\sigma_{2}^{z} \\sigma_{1}^{z}+0.165868 \\sigma_{3}^{z} \\sigma_{0}^{z} +0.12054625 \\sigma_{3}^{z}\\sigma_{1}^{z} \\\\\n", + "+0.17434925 \\sigma_{3}^{z} \\sigma_{2}^{z}-0.04532175 \\sigma_{3}^{x} \\sigma_{2}^{x} \\sigma_{1}^{y} \\sigma_{0}^{y}\\\\\n", + "+0.04532175 \\sigma_{3}^{x} \\sigma_{2}^{y} \\sigma_{1}^{y} \\sigma_{0}^{x}+0.04532175 \\sigma_{3}^{y} \\sigma_{2}^{x}\n", + "\\sigma_{1}^{x} \\sigma_{0}^{y} -0.04532175 \\sigma_{3}^{y} \\sigma_{2}^{y} \\sigma_{1}^{x} \\sigma_{0}^{x}$$" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "def pauli(positions=[], operators=[]):\n", + " op_list = [\n", + " operators[positions.index(j)] if j in positions else qutip.qeye(2)\n", + " for j in range(num_qubits)\n", + " ]\n", + " return qutip.tensor(op_list)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "coeff_fact = [\n", + " 0.81261,\n", + " 0.171201,\n", + " 0.2227965,\n", + " 0.16862325,\n", + " 0.174349,\n", + " 0.12054625,\n", + " 0.165868,\n", + " 0.04532175,\n", + "]\n", + "\n", + "paulis = [\n", + " pauli(),\n", + " pauli([0], [sz]) + pauli([1], [sz]),\n", + " pauli([2], [sz]) + pauli([3], [sz]),\n", + " pauli([1, 0], [sz, sz]),\n", + " pauli([3, 2], [sz, sz]),\n", + " pauli([2, 0], [sz, sz]) + pauli([3, 1], [sz, sz]),\n", + " pauli([2, 1], [sz, sz]) + pauli([3, 0], [sz, sz]),\n", + " pauli([3, 2, 1, 0], [sx, sx, sy, sy])\n", + " + pauli([3, 2, 1, 0], [sy, sy, sx, sx]),\n", + " pauli([3, 2, 1, 0], [sx, sy, sy, sx])\n", + " + pauli([3, 2, 1, 0], [sy, sx, sx, sy]),\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# H2 Molecule : 4 qubits in Jordan-Wigner mapping of the Hamiltonian\n", + "a = 10\n", + "reg = Register.from_coordinates(\n", + " [\n", + " [0, 0],\n", + " [a, 0],\n", + " [0.5 * a, a * np.sqrt(3) / 2],\n", + " [0.5 * a, -a * np.sqrt(3) / 2],\n", + " ],\n", + " prefix=\"q\",\n", + ")\n", + "reg.draw()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us keep the exact ground-state energy of the molecule for future reference, by diagonalizing it exactly - this is possible for such a small system, however, this quickly becomes an intractable problem for large molecules." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-1.8510459284448646\n" + ] + } + ], + "source": [ + "def cost_hamiltonian_JW():\n", + " H = (\n", + " -coeff_fact[0] * paulis[0]\n", + " + coeff_fact[1] * paulis[1]\n", + " - coeff_fact[2] * paulis[2]\n", + " + coeff_fact[3] * paulis[3]\n", + " + coeff_fact[4] * paulis[4]\n", + " + coeff_fact[5] * paulis[5]\n", + " + coeff_fact[6] * paulis[6]\n", + " - coeff_fact[7] * paulis[7]\n", + " + coeff_fact[7] * paulis[8]\n", + " )\n", + " return H\n", + "\n", + "\n", + "global H\n", + "H = cost_hamiltonian_JW()\n", + "exact_energy, ground_state = cost_hamiltonian_JW().groundstate()\n", + "print(exact_energy)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quantum Loop (VQS)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Much like in the *Using QAOA to solve a QUBO problem* notebook, we will use a mixed classical-quantum approach for minimizing the energy. The quantum part will do the exploration in Hilbert space, according to a certain set of parameters $\\theta_i, \\tau_j$, and the classical part will find the optimal parameters given the value of the energy after each loop. For now, we will ignore sampling problems and simply compute the exact expectation value of $H_{JW}$. See [this article by Xiao Yuan et al.](https://arxiv.org/abs/1812.08767) for details about VQS algorithms." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Two mixing Hamiltonians are used for the exploration of the solution space :\n", + "$H_1 = \\hbar / 2 \\sum_i \\sigma_i^x + \\sum_{j" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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71955ZUaNGiQMjIytHnzZt15550qKyvTK6+84mC1vhszZowKCws1bNgwVVRUaMmSJfq3f/s3ffHFFzpw4ICioqJanRD69eunAwcOOFPwCXj11VdVWVmp2bNne98L9uP3Y57j0tbvoGfdgQMHlJaW1mJ9RESE+vbtG5TH9fjx47rzzjt1xRVXtHjo3a233qozzjhDffv21bp167Ro0SJVVFTokUcecbBa30yZMkWXXHKJhgwZoh07duiuu+7S1KlTtX79eoWHh4fcMSwqKlJ8fHyrIelgOYZtnR98+ft54MCBNn9XPev8gfDSw82dO1dffPFFi/kgklqMMY8cOVL9+/fXhAkTtGPHDmVnZ3d3mZZNnTrV+/Npp52mMWPGaNCgQXrppZfUq1cvByvzv4KCAk2dOlUZGRne94L9+PV0DQ0Nuuyyy2SM0dNPP91i3R133OH9+bTTTlNUVJRuuOEG5efnB/xt6H/5y196fx45cqROO+00ZWdna82aNZowYYKDldnjueee08yZMxUTE9Pi/WA5hu2dHwIBw0Y+SElJUXh4eKvZ1AcPHlR6erpDVZ24m2++WW+88YZWr16tAQMGdNh2zJgxkqTt27d3R2l+l5SUpKFDh2r79u1KT09XfX29KisrW7QJxuO5e/duvf/++7ruuus6bBfsx89zXDr6HUxPT281gb6xsVFHjx4NquPqCS67d+/WypUrW/S6tGXMmDFqbGzUrl27uqdAP8rKylJKSor332WoHENJ+vDDD1VWVtbp76YUmMewvfODL38/09PT2/xd9azzB8KLD6KiopSXl6dVq1Z532tubtaqVas0duxYByvrGmOMbr75Zq1YsUIffPCBhgwZ0uk2JSUlkqT+/fvbXJ09ampqtGPHDvXv3195eXmKjIxscTzLyspUXl4edMfz+eefV1pamqZNm9Zhu2A/fkOGDFF6enqLY+Z2u7VhwwbvMRs7dqwqKyu1adMmb5sPPvhAzc3N3vAW6DzBZdu2bXr//feVnJzc6TYlJSUKCwtrNdwSDPbu3asjR454/12GwjH0KCgoUF5enkaNGtVp20A6hp2dH3z5+zl27Fht2bKlRRD1BPHhw4f7rVD44K9//auJjo42hYWFZuvWreb66683SUlJLWZTB4s5c+aYxMREs2bNGlNRUeFdjh07ZowxZvv27ebee+81GzduNDt37jSvvfaaycrKMuecc47Dlftu/vz5Zs2aNWbnzp3mn//8p5k4caJJSUkxhw4dMsYYc+ONN5qBAweaDz74wGzcuNGMHTvWjB071uGqrWlqajIDBw40d955Z4v3g/X4VVdXm88++8x89tlnRpJ55JFHzGeffea90uaBBx4wSUlJ5rXXXjObN282F110kRkyZIj5/vvvvZ8xZcoUM3r0aLNhwwbz0UcfmZNPPtlcccUVTu1SKx3tY319vbnwwgvNgAEDTElJSYvfTc8VGuvWrTOPPvqoKSkpMTt27DAvvPCCSU1NNVdddZXDe/YvHe1fdXW1+c1vfmPWr19vdu7cad5//31zxhlnmJNPPtkcP37c+xnBfAw9qqqqTGxsrHn66adbbR/ox7Cz84Mxnf/9bGxsNCNGjDCTJk0yJSUl5p133jGpqalm0aJFfquT8GLBk08+aQYOHGiioqLMWWedZYqLi50uqUsktbk8//zzxhhjysvLzTnnnGP69u1roqOjTU5OjlmwYIGpqqpytnALLr/8ctO/f38TFRVlTjrpJHP55Zeb7du3e9d///335qabbjJ9+vQxsbGxZvr06aaiosLBiq179913jSRTVlbW4v1gPX6rV69u89/l1VdfbYz51+XSd999t+nXr5+Jjo42EyZMaLXvR44cMVdccYXp3bu3SUhIML/61a9MdXW1A3vTto72cefOne3+bq5evdoYY8ymTZvMmDFjTGJioomJiTGnnHKKuf/++1uc/J3U0f4dO3bMTJo0yaSmpprIyEgzaNAg8+tf/7rVfwAG8zH0+MMf/mB69eplKisrW20f6Mews/ODMb79/dy1a5eZOnWq6dWrl0lJSTHz5883DQ0NfqvT9f+LBQAACArMeQEAAEGF8AIAAIIK4QUAAAQVwgsAAAgqhBcAABBUCC8AACCoEF4AAEBQIbwAAICgQngBAABBhfACAACCCuEFAAAEFcILAAAIKv8PmGkBG7NBfFYAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(\n", + " [quantum_loop(pars, gggg) for pars in loop_ising_results.allvecs], \"k\"\n", + ")\n", + "plt.axhline(exact_energy, color=\"red\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Seems like we can cut on calculation time by only allowing $100$ iterations, since we don't get much more accurate afterwards." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Estimating Jordan-Wigner $H_2$ Hamiltonian with classical shadows" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Randomized measurements" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We now consider the real-life problem where we don't have access to the exact value $\\bra{\\Psi(\\theta_i, \\tau_j)} H_{JW} \\ket{\\Psi(\\theta_i, \\tau_j)}$. It can be estimated with classical shadows.\n", + "We modify the quantum loop to add classical shadow estimation of the several Pauli strings making up the $H_{JW}$ Hamiltonian : this is the perfect setting to do so, because we have multiple Pauli strings and most of them have low weight." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "def exp_value_JW(exp_values):\n", + " return (\n", + " -coeff_fact[0] * exp_values[0]\n", + " + coeff_fact[1] * exp_values[1]\n", + " - coeff_fact[2] * exp_values[2]\n", + " + coeff_fact[3] * exp_values[3]\n", + " + coeff_fact[4] * exp_values[4]\n", + " + coeff_fact[5] * exp_values[5]\n", + " + coeff_fact[6] * exp_values[6]\n", + " - coeff_fact[7] * exp_values[7]\n", + " + coeff_fact[7] * exp_values[8]\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "def quantum_loop_shadows(param, in_state, shadow_size=20, r=reg):\n", + " \"\"\"\n", + " Args:\n", + " param (np.array): time parameters for each mixing Hamiltonian. There are 2p time parameters in param.\n", + " in_state (qubit.Qobj): initial state.\n", + " \"\"\"\n", + " seq = Sequence(r, DigitalAnalogDevice)\n", + " seq.declare_channel(\"ch0\", \"rydberg_global\")\n", + " middle = len(param) // 2\n", + "\n", + " for tau, t in zip(param[middle:], param[:middle]):\n", + " pulse_1 = Pulse.ConstantPulse(tau, 1.0, 0, 0)\n", + " pulse_2 = Pulse.ConstantPulse(t, 1.0, 1.0, 0)\n", + " seq.add(pulse_1, \"ch0\")\n", + " seq.add(pulse_2, \"ch0\")\n", + "\n", + " seq.measure(\"ground-rydberg\")\n", + " simul = QutipEmulator.from_sequence(seq, sampling_rate=0.01)\n", + " simul.set_initial_state(in_state)\n", + "\n", + " # Classical shadow estimation\n", + " # Theoretical shadow size and number of clusters :\n", + " # shadow_size, K = compute_shadow_size(0.1, 0.5, paulis)\n", + " # We use K=4 to allow for quick simulation\n", + " K = 4\n", + " rho = simul.run().get_final_state().proj()\n", + " outcomes, unitary_ids = calculate_classical_shadow(rho, shadow_size)\n", + " snapshots = [\n", + " snapshot_state(outcomes[ns], unitary_ids[ns])\n", + " for ns in range(shadow_size)\n", + " ]\n", + " meds = [_median_of_means(obs, snapshots, K) for obs in paulis]\n", + " return exp_value_JW(meds)\n", + "\n", + "\n", + "def loop_JW_shadows(param, in_state, shadow_size=20):\n", + " res = minimize(\n", + " quantum_loop_shadows,\n", + " param,\n", + " method=\"Nelder-Mead\",\n", + " args=(in_state, shadow_size),\n", + " options={\"return_all\": True, \"maxiter\": 100, \"adaptive\": True},\n", + " )\n", + " return res" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "shadow_sizes = [10, 20, 40, 60, 80, 100]\n", + "energies = []\n", + "for shadow_size in shadow_sizes:\n", + " energies.append(\n", + " abs(\n", + " loop_JW_shadows(param, gggg, shadow_size=shadow_size).fun\n", + " - exact_energy\n", + " )\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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HzV48OAr/UqoBoM7NFGgr6fScgq14dBpDWgXYnZJAACgnrEY1fEI+Gf69eun1157TYMGDbqi4202W7VM55eZmanExERt375dkyZNuqJzxMTEqG/fvpo1a5YkyeFwKCIiQo8++qimTJlS4TF2u13XXnutfvvb32rt2rXKzMzUkiVLLvua2dnZCgwMVFZWlgICAq6obvxkyn+3aeGmY7qrX0vNvK2H2eUAAIA6oCp5zSU93H/+8581ZcoUpaenu+L0FQoODtbQoUP12GOP6Z133lF8fLx8fHw0ZMiQKw7bRUVFio+PV2xsrHPMarUqNjZWcXFxlR737LPPqmnTpnrggQcu6zqFhYXKzs4us6H6lLaVLN+RrGK7w+RqAABAfeOSwH3rrbdqw4YN6tSpkx5++OFq7aeuzAcffKBhw4YpNTVVr7zyiq655hr5+/urS5cuGj169BWdMz09XXa7XaGhoWXGQ0NDlZKSUuEx69at0zvvvKP58+df9nVmzpypwMBA58ZS9NXrmraNFdLQW5l5xVq3v+b+EggAACC5KHDv3r1bH330kR555BGdPHlSU6dOVbdu3dSwYUPFxMS44pIaPny4pk6dqoULFyopKUkZGRmaM2eOMjMz1bhxY5dc8+dycnJ03333af78+QoJufxe4alTpyorK8u5HTt2zIVV1j82q0XDe4RJkpZuZbYSAABQs1yy8E3Hjh3VsWNH3X777c6xrKwsJSYm1tgiNP7+/ho/frzatGmjzz777IrOERISIpvNptTU1DLjqampCgsLK7f/gQMHdPjwYY0YMcI55nCca2Hw8PDQnj171K5du3LHeXt7y9vb+4pqxOUZEdVM78Ud0de7UlVQbJePp83skgAAQD3hkifcBQUF5cYCAwN17bXXXnE/9ZW67rrrtHz58is61svLS3369NGqVaucYw6HQ6tWrVL//v3L7d+5c2dt375dW7dudW4333yzfvGLX2jr1q20ipiod8sgNW/kq7OFJVq955TZ5QAAgHrEJU+4GzZsqPbt2ysqKkqRkZGKjIxUVFSUWrZs6YrLSZKaNGminj17Oq8ZFRWlDh06aPPmzTpz5swVn3fy5MkaO3asoqOj1a9fP73xxhvKzc3VuHHjJEljxoxR8+bNNXPmTPn4+Kh79+5lji+dBvHn46hZVqtFv44M19vfH9TSxGTd0D3c7JIA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MRV9duH4iRMnyowPGTJEH3zwgX788UcNHTpUq1evVteuXdW0aVMNHTpUa9as0f79+9WuXTt9//338vf3V+/evSv9Hhd68cUXtX37di1dulRLly5VUFCQBg0apJtvvln33nuvfHx8Lus8pe6//34lJCTogQce0GOPPVbms8OHD0uSVq5cecmFidLT09WpU6cqXRtA3UHgBgCTNWrUSA8//LCaNWumW265Rd99953y8vLk5+dXZj+r9fL+UfLs2bO64447lJGRoenTp+vOO+9Uq1at5OvrK4vForvvvlsLFiwo96JldasshA4dOlQffPCBVq9ercjISG3fvl0TJkxwfvbMM89o9erVys/PV3p6um688cYyLypeTEREhDZv3qxvv/1Wy5Yt05o1a5zh++WXX1ZcXJwaN258Wed67rnn9PHHH2vQoEF66623yn1e+vS8ffv2Gjhw4EXPdbnXBFA3EbgBwE388pe/lCTZ7XZlZmaWC9yXa+3atTp9+rRGjRqlZ555ptznBw8eLDcWHh4uSTpy5EiF56xovFmzZhc9pvQJcPPmzcuMDxkyRNK5dpGoqCgZhuFsGbnmmmvk7e3tDNzS5beTlPLw8ND111/vbP84cuSIfvvb3+rbb7/VSy+9pJdffvmS5/jss880Y8YMtWrVSosXL5aXl1e5fUr/xaFz587697//XaUaAdQv9HADQA251BPl0unwvLy8FBIScsXXOXPmjKSKW1D279+vhISEcuODBw+WJH388cflPispKdF///vfcuODBg2SJK1YsaLCucA//PDDMucu1a5dO0VEROjHH3/UihUrZLFYnKHax8fH2cdd1f7tyrRq1UpPPvmkJGnHjh2X3D8xMVH33Xef/Pz89Pnnn1c6b3rfvn0VGBioNWvWKCMj46pqBFC3EbgBoIZMmzZNf/rTn8q8rFjqxIkT+t3vfidJuvnmmyt8onq5Sl+kXLx4cZke7szMTD3wwAMqLi4ud8ztt9+uxo0ba/Xq1Xrvvfec44ZhaMaMGTp69Gi5Y9q2bavhw4crJydHjz32WJnzxsXFac6cObLZbJo4cWK5Y0vn437//ffVtWvXMqF26NChOn78uL766qsq9W9L0uuvv66UlJRy41999ZUkVbiwzoXS0tJ0yy23KC8vT++//76ioqIq3dfb21tPPPGEcnJydNttt1X4LwcnTpzQBx98cNn1A6ibaCkBgBpy9uxZ/f3vf9crr7yijh07qmvXrvLx8dHx48e1YcMGFRcXq3379nrjjTeu6jrR0dH61a9+pZUrV6pjx47OJ8SrV69WSEiIbrnlFn3++edljvH399c777yj3/zmN7r//vs1Z84ctW3bVomJidq3b58efPBBzZ8/v9y13n77bQ0ePFjvv/++1qxZo/79+ystLU2rV6+W3W7Xq6++qp49e5Y7bsiQIfrwww9VUFBQ7gl2aR936WceHpf/R9UzzzyjP/7xj4qKilKHDh1kGIYSExO1d+9eBQcH649//ONFj587d66OHDmisLAwffHFF/riiy/K7TNo0CCNHz9ekjRlyhTt3r1bH3zwgbp06aJevXqpTZs2Kioq0p49e7Rr1y5FRkY6Z2wBUD8RuAGghvzlL39RdHS0/ve//ykxMVFr165VVlaWAgIC1K9fP91yyy165JFH1KBBg6u+1ueff64XXnhBH3/8sZYvX66mTZvqzjvv1PPPP6//+7//q/CY0hc2Z8yYoY0bNyopKUl9+/bVP//5T+3Zs6fCwN28eXNt2rRJM2fO1JIlS7R48WL5+fnpuuuu0//93/9VOJWhVLZN5OeBu7SPu7CwsMrtJG+++aZWrFih+Ph4LV++XNK5p9qTJ0/W5MmTy/WT/5zdbpckpaSklHnS/3Olgdtqter999/XqFGjNG/ePG3atEkJCQkKCgpSRESE/vSnP2n06NFV+g4A6h6L4erX1AEAAIB6jB5uAAAAwIUI3AAAAIALEbgBAAAAFyJwAwAAAC5E4AYAAABciMANAAAAuBCBGwAAAHAhAjcAAADgQgRuAAAAwIUI3AAAAIALEbgBAAAAFyJwAwAAAC5E4AYAAABc6P8BzdP3cotcEBIAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(8, 5))\n", + "plt.xlabel(\"Shadow size\", fontsize=15)\n", + "plt.ylabel(r\"$|\\frac{E - E_{ground}}{E_{ground}}|$\", fontsize=20)\n", + "plt.plot(shadow_sizes, [-e / exact_energy for e in energies])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As could be expected, the estimation can be worse than what we got before : we added both randomness and sampling issues to the problem. Raising shadow size will allow more and more precise results. However, it can also be closer to the exact value for the same reasons." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Derandomized measurements" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we try out the derandomized measurements method. To implement this one, we need to decompose the Hamiltonian into individual Pauli strings, rather than group them when they share the same leading coefficient as we did before, as it reduced the number of estimations." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "coeff_non_fact = [\n", + " -0.81261,\n", + " 0.171201,\n", + " 0.171201,\n", + " -0.2227965,\n", + " -0.2227965,\n", + " 0.16862325,\n", + " 0.174349,\n", + " 0.12054625,\n", + " 0.12054625,\n", + " 0.165868,\n", + " 0.165868,\n", + " -0.04532175,\n", + " -0.04532175,\n", + " 0.04532175,\n", + " 0.04532175,\n", + "]\n", + "\n", + "paulis_str = [\n", + " \"1111\",\n", + " \"Z111\",\n", + " \"1Z11\",\n", + " \"11Z1\",\n", + " \"111Z\",\n", + " \"ZZ11\",\n", + " \"11ZZ\",\n", + " \"Z1Z1\",\n", + " \"1Z1Z\",\n", + " \"1ZZ1\",\n", + " \"Z11Z\",\n", + " \"YYXX\",\n", + " \"XXYY\",\n", + " \"XYYX\",\n", + " \"YXXY\",\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "def exp_value_JW_non_fact(outcomes):\n", + " return sum(\n", + " [\n", + " c * exp_value(sigma, outcomes)\n", + " for c, sigma in zip(coeff_non_fact, paulis_str)\n", + " ]\n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, we ask the derandomization algorithm to return $60$ suitable Pauli measurements regarding our input Pauli observables. $60$ is arbitrary, but is small enough that the algorithm runs quickly and large enough that it gives good results." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ZZZZ measurements : 18, XXYY measurements : 11, YXXY measurements : 11, XYYX measurements : 10, YYXX measurements : 10 : total = 60 measurements\n" + ] + } + ], + "source": [ + "measurements = derandomization(60, paulis_str)\n", + "print(\n", + " f\"ZZZZ measurements : {measurements.count('ZZZZ')}, XXYY measurements : {measurements.count('XXYY')}, \"\n", + " + f\"YXXY measurements : {measurements.count('YXXY')}, XYYX measurements : {measurements.count('XYYX')}, \"\n", + " + f\"YYXX measurements : {measurements.count('YYXX')} : total = 60 measurements\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see, since all Pauli observables appearing in the Jordan-Wigner Hamiltonian involving the $Z$-basis never involve another basis, we find that it is always worth it to measure Pauli string $ZZZZ$ rather than $ZZZX$, or $ZYZZ$, etc. This is a sign that our cost function is doing its job !" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [], + "source": [ + "def quantum_loop_derand(param, in_state, r=reg):\n", + " \"\"\"\n", + " Args:\n", + " param (np.array): time parameters for each mixing Hamiltonian. There are 2p time parameters in param.\n", + " in_state (qubit.Qobj): initial state.\n", + " \"\"\"\n", + " seq = Sequence(r, DigitalAnalogDevice)\n", + " seq.declare_channel(\"ch0\", \"rydberg_global\")\n", + " middle = len(param) // 2\n", + "\n", + " for tau, t in zip(param[middle:], param[:middle]):\n", + " pulse_1 = Pulse.ConstantPulse(tau, 1.0, 0, 0)\n", + " pulse_2 = Pulse.ConstantPulse(t, 1.0, 1.0, 0)\n", + " seq.add(pulse_1, \"ch0\")\n", + " seq.add(pulse_2, \"ch0\")\n", + "\n", + " seq.measure(\"ground-rydberg\")\n", + " simul = QutipEmulator.from_sequence(seq, sampling_rate=0.05)\n", + " simul.set_initial_state(in_state)\n", + "\n", + " # Classical shadow estimation\n", + " rho = simul.run().get_final_state().proj()\n", + " outcomes = classical_shadow_derand(rho, measurements)\n", + " return exp_value_JW_non_fact(outcomes)\n", + "\n", + "\n", + "def loop_JW_derand(param, in_state):\n", + " res = minimize(\n", + " quantum_loop_derand,\n", + " param,\n", + " method=\"Nelder-Mead\",\n", + " args=in_state,\n", + " options={\"return_all\": True, \"maxiter\": 150, \"adaptive\": True},\n", + " )\n", + " return res" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "measurement_sizes = [20, 30, 40, 60, 80, 100]\n", + "energies_derand = []\n", + "for meas_size in measurement_sizes:\n", + " measurements = derandomization(meas_size, paulis_str)\n", + " energies_derand.append(\n", + " abs(loop_JW_derand(param, gggg).fun - exact_energy) / abs(exact_energy)\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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c3PDrVu3sGfPHkyaNInX5bamXIewsDAUFBTo/Wbhl19+gVarRWhoaNsU2iaPjlKHMHfuXGFnZycOHDigN/VWWVmZrs1zzz0nunfvLn755RcRGxsrwsLCRFhYmIRVt42FCxeKgwcPiitXroikpCSxcOFCIZPJxN69e4UQpntdDLlzlhUhTPfavPLKK+LAgQPiypUr4ujRo2Ls2LHCyclJ5OTkCCFM97qcPHlSmJmZiXfffVdcvHhRfPvtt8LKykp88803ujbvvfeesLe3F9u2bRNJSUli0qRJnXKqNkM0Go3o3r27eOONN+qtM9Xvmaefflp4eHjopj3cunWrcHJyEq+//rqujal+z+zevVvs2rVLpKamir1794qgoCARGhoqqqqqhBCmc12Ki4tFfHy8iI+PFwDEhx9+KOLj48W1a9eEEE27DhEREWLAgAHixIkT4siRI6J3796c9pCkAcDg58svv9S1KS8vF3/961+Fg4ODsLKyEo888ojIzMyUrug28swzz4gePXoIpVIpunbtKsaMGaML40KY7nUx5I+B3FSvzZQpU4Sbm5tQKpXCw8NDTJkyRW+ubVO9LkII8dNPP4mAgABhYWEh/Pz8xLp16/TWa7VasWTJEuHi4iIsLCzEmDFjxPnz5yWqtm3t2bNHADB4vqb6PVNUVCTmz58vunfvLlQqlfD29hZvvvmmqKys1LUx1e+ZzZs3C29vb6FUKoWrq6t4/vnnRUFBgW69qVyX/fv3G8wvTz/9tBCiadfh5s2bYurUqcLGxkao1Woxa9YsUVxc3GbnIBPijlddERERERFRm+IYciIiIiIiCTGQExERERFJiIGciIiIiEhCDORERERERBJiICciIiIikhADORERERGRhBjIiYiIiIgkxEBORNQAmUym+xw/frzBdt9//72unZeXV9sVSJ3azJkzIZPJcODAAalLISIjYyAnImqCb7/9tsF133zzTRtWQlL76quvIJPJsHz5cqlLIaJOgoGciKgRCoUC/fv3x+bNm1FTU1Nv/c2bN7F7924MHDhQguqoM1uxYgXOnTuHIUOGSF0KERkZAzkR0V1MmzYNeXl52LNnT711mzdvRnV1NaZPny5BZdSZubm5wc/PD1ZWVlKXQkRGxkBORHQXTz75JGQymcGhKd988w1sbGwwadKkRvdx7tw5zJw5E56enrCwsICLiwueeOIJnDlzpl7biooKfPHFF5g0aRK8vb1haWkJe3t73H///fjuu+8M7r+qqgqffvopBg8eDEdHR1hZWcHLywsPPfRQvW28vLwgk8kM7ufAgQOQyWSYOXOm3vI7xzPv2bMHo0ePhr29PWQyGQoKCnTtdu/ejQkTJqBr166wsLCAt7c3FixYgJs3b9Y71p373LdvH+6//37Y2trC2dkZf/nLX1BYWAgAyMnJwf/93//Bw8MDKpUKQ4YMaXRc9YkTJ/DYY4/Bzc0NSqUS3bp1w5w5c3D9+vV6bZcvXw6ZTIavvvoKycnJmDhxIhwcHGBtbY2RI0fi2LFjeu1HjRqFWbNmAQDefvttvecMvvrqqwZrqtOcr5OhMeR1yxr7/PHa5OfnY9GiRejXrx8sLS1hZ2eHBx54ADt27LhrvUTUNsykLoCIqL3z9PTE/fffj+3bt6OkpAQ2NjYAgNTUVBw/fhxPPfVUo72YUVFReOKJJ1BZWYng4GAMHToUaWlp+P777/HTTz9h165duP/++3Xtr169ijlz5sDd3R2+vr4YMmQIsrKycOzYMRw+fBgpKSn1xi9PmzYNP/zwA2xtbTFixAio1Wqkp6fjyJEjKCkpwRNPPNEq12Ljxo34/PPPERISgvHjx+Py5cu6cL9w4UKsXLkSSqUSgwcPhpubGxITE/HRRx9h+/btOHr0KFxcXOrt88cff8SaNWsQFhaGiIgI/Prrr/j8889x8eJF/PDDDwgLC4NGo8GIESNw9epVnDhxAhEREfjtt9/Qv39/vX19+umneOGFFwAAgwcPxogRI3D+/Hl88cUX2L59Ow4ePIi+ffvWqyE2NhbPP/88evXqhfDwcKSkpODQoUMYM2YMfvvtNwQEBAAAIiIiUFNTg6NHjyIoKAjBwcG6ffj4+Nz1+t3r1+m+++4zuFyj0WDTpk3QaDRQKBS65RcuXMDYsWORlpYGLy8vhIeHo7i4GL/++isefvhhvP/++3j11VfvWjcRGZkgIiKDAAiFQiGEEGL9+vUCgNiwYYNu/f/7f/9PABB79uwRmZmZAoDo0aOH3j6uXLkirK2thY2NjYiOjtZbt2vXLmFubi48PT1FZWWlbnleXp6Ijo4WWq1Wr31qaqrw8vIScrlcXLlyRW953bHz8vL0tikvLxfHjh3TW9ajRw/R0D//+/fvFwDE008/rbf86aefFgAEAPHdd9/V2+77778XAERAQIC4ePGibrlWqxVLly4VAMSUKVMM7lMul4sdO3bolhcVFYmAgAABQPTr109Mnz5dVFVV6da/9dZbAoCYMWOG3v6OHz8uFAqF8PDwELGxsXrrPv/8cwFAhIaG6i1ftmyZ7rw++eQTvXUvvfSSACCeeuopveVffvmlACCWLVtW7zo0prlfp7rrs3///rvu+8UXXxQAxEMPPSQ0Go0QQoiamhrRv39/AUD84x//0C0XQoiLFy+Knj17CoVCIZKTk5t1HkTU+hjIiYgacGcgv3XrlrCwsBDjxo3Trff19RVubm6ipqamwUA+f/58AUD861//MniMuiC1devWJtVU94PBP//5T92yEydOCAAiMjKySfu4l0A+YcIEg9sFBQUJAAbDnVarFcHBwUKhUIjc3Nx6+5w+fXq9bT755BMBQKjVapGfn6+3rqCgQMhksnrXetKkSQKA+OmnnwzWOHHiRAFAnDp1SresLpAPHz68Xvu8vDyDX9OWBvLmfp2aGsjrvif69esnioqKdMt//PFHAUA8+uijBrfbunWrACBefPHFJp8DERkHx5ATETWBvb09JkyYgJiYGGRlZeG3337D+fPn8cQTT+gNEfijvXv3AgAmT55scP2IESMAACdPnqy37siRI/jb3/6GuXPnYtasWZg5cya2bNkCALh48aKunZ+fH6ytrfHzzz/j/fffR0ZGRovP824mTpxYb1lOTg4SExPRu3dv3dCOO8lkMgwfPhwajQZxcXH11o8bN67eMm9vbwBASEgIHBwc9NbZ2dmhS5cuyMzM1C3TarWIiYmBlZUVwsPDDdbe2LU2VIOjo2O949wLY3ydDh8+jL/+9a9wdHTETz/9BFtbW926e/neI6K2xTHkRERNNH36dGzduhXfffcdrly5olvWmKtXrwIAPDw8Gm2Xl5en+3NhYSEmT56MX375pcH2xcXFuj+r1WqsX78ezz77LF5//XW8/vrr6NOnD0aPHo2nnnoKw4cPv9upNVn37t3rLas7x4sXLzb4sGidO8+zjqFrUzdOv6HrZmNjo/egaF5eHkpKSgAASqWy2TV069bNYFtbW1vk5+c3ur+mau2v07Vr1/Doo49CCIEtW7bofoipU/d1mTZtGqZNm9bgfgxdDyJqWwzkRERN9Kc//Qn29vb4+uuvkZGRgb59+951/nGtVgsAePrppxttFxoaqvvzG2+8gV9++QUjR47E22+/jYCAANjb20OhUGDv3r0IDw+HEEJv+6lTp2Ls2LHYtm0b9u7di4MHD+Lf//43/v3vf2PBggVYtWpVk86xrt6GqFSqBrdxdXVtsHe6To8ePeotk8sb/mVtY+sM1WBjY4NHH3200bb+/v4tPs69aq2vU2lpKSZOnIjc3Fx8+umnGD16dL02ddckIiLC4MO0dZycnFp2MkTUahjIiYiayMLCAo899hjWr18PAHjxxRfvuk23bt1w+fJlrFq1Co6Ojk06zo8//giFQoHt27dDrVbrrUtNTW1wu65du2LOnDmYM2cOhBDYs2cPpkyZgg8//BDPPPOMLojW9SDfOWNMnbS0tCbVeKe63mUnJ6cmTf1nDE5OTlCpVJDL5fjyyy/v2lMvpaZ+nRoihMBTTz2FpKQkzJ07F3PnzjXYru7rMmfOnLv+kEJE0uIYciKiZnjqqafg6OgIJyenRocB1HnwwQcB1Ibsprp16xbUanW9MA4A33//fZP2IZPJEBERgQkTJgCA3nznbm5uAGqnxPuj6OjoJtdZp1u3bvDz88PZs2cN7rMtmJmZYdSoUSgqKkJMTIxRj1X3A42hN7c2V2Nfp4YsXboUP/74I0aPHo1//vOfDbZryfceEUmDgZyIqBlGjBiBvLw85ObmGhx+8UevvPIKLC0t8eqrr2Lr1q311ldWVuKHH37AjRs3dMv69OmDW7duYfPmzXptP/roI+zfv7/ePuLj47F161ZUVVXpLc/Pz8eJEycA1M6lXmfkyJEAal/NrtFodMs3bdqETZs23fWcDFmyZAm0Wi0effRRJCQk1Ft/8+ZN3W8WjOXNN9+EXC7HrFmzDL44qKSkBP/5z39QXl5+T8dxd3cHAJw/f75Z2zX362TI5s2b8be//Q3e3t7YsmULzMwa/kX3o48+in79+uHbb7/FO++8g8rKSr31QggcPXoUR48ebdZ5EFHr45AVIiIj8vHxwaZNm/Dkk0/i0UcfhY+PD/r27Qtra2ukp6fj1KlTKC0tRXx8vG6IwaJFizB9+nQ88cQTWLNmDbp164bExESkpKTg5ZdfxkcffaR3jLqH++zs7BASEgJXV1cUFBTg0KFDKC4uxsMPP4ywsDBd++effx5r167FDz/8gH79+iEwMBAXL17E6dOnMX/+/Hr7b4onn3wSZ86cwd///ncMGjQIwcHB6NWrF4QQuHz5MpKSkmBjY4O//OUv93ZBG3HfffdhzZo1mDdvHkaPHo2AgAD06dMH5ubmuHr1KhISElBZWYnJkyfD0tKyxccZOnQonJ2d8cMPP2DUqFHw9vaGXC7HM888g2HDhjW4XXO/ToYsXrwYQO0PBa+88orBNgsXLoSfnx/MzMwQFRWF8PBwLF26FKtXr0ZgYCCcnZ2Rl5eHhIQE5OTk4KOPPmrVB3+JqPkYyImIjGzSpElISkrChx9+iOjoaERHR8Pc3Bzu7u54+OGHMXnyZPTr10/Xftq0aXBwcMA777yDhIQEJCcnIyQkBJ9++imEEPUC89ChQ/G3v/0Nv/zyC86fP4/Dhw/DwcEBgYGBmD17dr2ZYFxcXHDo0CG89tprOHjwINLT0zFo0CBER0dDJpO1KJADwLvvvovw8HCsXr0aR48eRXJyMtRqNTw8PDB37lw89thjLdpvczz33HMYOnQoPv74Yxw4cAA7duyAlZUVPDw8MG3aNEyePBl2dnb3dAyVSoWff/4ZixcvxsmTJ3Ho0CEIIXDfffc1Gsib+3UypO43GkeOHMGRI0cMtpk5cyb8/PwAAL1790Z8fDxWr16NrVu34tdff0VNTQ1cXV0xYMAATJw4EY8//ngLrgIRtSaZ+OOj+kRERERE1GY4hpyIiIiISEIM5EREREREEmIgJyIiIiKSEAM5EREREZGEGMiJiIiIiCTEQE5EREREJCEGciIiIiIiCTGQExERERFJiIGciIiIiEhCDORERERERBJiICciIiIikhADORERERGRhBjIiYiIiIgk9P8BaiBGRzR6fwMAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(8, 5))\n", + "plt.xlabel(\"Measurement size\", fontsize=15)\n", + "plt.ylabel(r\"$|\\frac{E - E_{ground}}{E_{ground}}|$\", fontsize=20)\n", + "plt.plot(measurement_sizes, energies_derand)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We consistently obtain accurate results using this derandomized technique, and we obtain them far quicker than when dealing with randomized classical shadows. For roughly the same number of samples ($\\sim 60$ for each method, be it for shadow size or number of measurements), we experience much less computing time using the derandomized method. This was to be expected : by restricting the observables to Pauli strings, we allow for efficient estimation that can be easily computed in $O(M\\times n)$, as well as remove randomness problematic with higher-weight observables (such as $YYXX$ or $YXXY$).\n", + "\n", + "Note that we obtain $2\\%$ accuracy after about $50$ $Z-$ basis measurements (fluorescence) of the output state, rotated before each sampling in the bases returned by the derandomization algorithm." + ] + } + ], + "metadata": { + "celltoolbar": "Tags", + "kernelspec": { + "display_name": "pulserenv", + "language": "python", + "name": "python3" }, - "nbformat": 4, - "nbformat_minor": 5 + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 } diff --git a/tutorials/quantum_simulation/Spin chain of 3 atoms in XY mode.ipynb b/tutorials/quantum_simulation/Spin chain of 3 atoms in XY mode.ipynb index e87f3fb3..515b412b 100644 --- a/tutorials/quantum_simulation/Spin chain of 3 atoms in XY mode.ipynb +++ b/tutorials/quantum_simulation/Spin chain of 3 atoms in XY mode.ipynb @@ -69,7 +69,7 @@ "outputs": [], "source": [ "coords = np.array([[0, 0]])\n", - "qubits = dict(enumerate(coords))\n", + "qubits = {f\"q{i}\": coord for (i, coord) in enumerate(coords)}\n", "\n", "reg = Register(qubits)\n", "seq = Sequence(reg, MockDevice)\n", @@ -147,7 +147,7 @@ "outputs": [], "source": [ "coords = np.array([[-8.0, 0], [0, 0], [8.0, 0]])\n", - "qubits = dict(enumerate(coords))\n", + "qubits = {f\"q{i}\": coord for (i, coord) in enumerate(coords)}\n", "\n", "reg = Register(qubits)\n", "seq = Sequence(reg, MockDevice)\n", @@ -155,7 +155,7 @@ "reg.draw()\n", "\n", "# State preparation using SLM mask\n", - "masked_qubits = [1, 2]\n", + "masked_qubits = [\"q1\", \"q2\"]\n", "seq.config_slm_mask(masked_qubits)\n", "masked_pulse = Pulse.ConstantDetuning(BlackmanWaveform(200, np.pi), 0, 0)\n", "seq.add(masked_pulse, \"ch0\")\n", @@ -236,7 +236,7 @@ "outputs": [], "source": [ "coords = np.array([[-1.0, 0], [0, 0], [np.sqrt(2 / 3), np.sqrt(1 / 3)]]) * 8.0\n", - "qubits = dict(enumerate(coords))\n", + "qubits = {f\"q{i}\": coord for (i, coord) in enumerate(coords)}\n", "\n", "reg = Register(qubits)\n", "seq = Sequence(reg, MockDevice)\n", @@ -259,7 +259,7 @@ "outputs": [], "source": [ "# State preparation using SLM mask\n", - "masked_qubits = [1, 2]\n", + "masked_qubits = [\"q1\", \"q2\"]\n", "seq.config_slm_mask(masked_qubits)\n", "masked_pulse = Pulse.ConstantDetuning(BlackmanWaveform(200, np.pi), 0, 0)\n", "seq.add(masked_pulse, \"ch0\")\n", @@ -286,17 +286,17 @@ "plt.figure(figsize=[16, 18])\n", "plt.subplot(311)\n", "plt.plot(expectations[0])\n", - "plt.ylabel(\"Excitation of atom 0\", fontsize=\"x-large\")\n", + "plt.ylabel(\"Excitation of atom q0\", fontsize=\"x-large\")\n", "plt.xlabel(\"Time ($\\mu$s)\", fontsize=\"x-large\")\n", "plt.ylim([0, 1])\n", "plt.subplot(312)\n", "plt.plot(expectations[1])\n", - "plt.ylabel(\"Excitation of atom 1\", fontsize=\"x-large\")\n", + "plt.ylabel(\"Excitation of atom q1\", fontsize=\"x-large\")\n", "plt.xlabel(\"Time ($\\mu$s)\", fontsize=\"x-large\")\n", "plt.ylim([0, 1])\n", "plt.subplot(313)\n", "plt.plot(expectations[2])\n", - "plt.ylabel(\"Excitation of atom 2\", fontsize=\"x-large\")\n", + "plt.ylabel(\"Excitation of atom q2\", fontsize=\"x-large\")\n", "plt.xlabel(\"Time ($\\mu$s)\", fontsize=\"x-large\")\n", "plt.ylim([0, 1])\n", "plt.show()"